Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which part of the C standard allows this code to compile?

Tags:

c

I was bug-fixing some code and the compiler warned (legitimately) that the function dynscat() was not declared — someone else's idea of an acceptable coding standard — so I tracked down where the function is defined (easy enough) and which header declared it (none; Grrr!). But I was expecting to find the details of the structure definition were necessary for the extern declaration of qqparse_val:

extern struct t_dynstr qqparse_val;

extern void dynscat(struct t_dynstr *s, char *p);
extern void qqcat(char *s);

void qqcat(char *s)
{
    dynscat(&qqparse_val, s);
    if (*s == ',')
        dynscat(&qqparse_val, "$");
}

The qqcat() function in the original code was static; the extern declaration quells the compiler warning for this snippet of the code. The dynscat() function declaration was missing altogether; again, adding it quells a warning.

With the code fragment shown, it's clear that only the address of the variable is used, so it makes sense at one level that it does not matter that the details of the structure are not known. Were the variable extern struct t_dynstr *p_parseval;, you'd not be seeing this question; that would be 100% expected. If the code needed to access the internals of the structure, then the structure definition would be needed. But I'd always expected that if you declared that the variable was a structure (rather than a pointer to the structure), the compiler would want to know the size of the structure — but apparently not.

I've tried provoking GCC into complaining, but it doesn't, even GCC 4.7.1:

gcc-4.7.1 -c -Wall -Wextra -std=c89 -pedantic surprise.c

The code has been compiling on AIX, HP-UX, Solaris, Linux for a decade, so it isn't GCC-specific that it is accepted.

Question

Is this allowed by the C standard (primarily C99 or C11, but C89 will do too)? Which section? Or have I just hit on an odd-ball case that works on all the machines it's ported to but isn't formally sanctioned by the standard?

like image 805
Jonathan Leffler Avatar asked Aug 30 '12 15:08

Jonathan Leffler


1 Answers

What you have is an incomplete type (ISO/IEC 9899:1999 and 2011 — all these references are the same in both — §6.2.5 ¶22):

A structure or union type of unknown content (as described in §6.7.2.3) is an incomplete type.

An incomplete type can still be an lvalue:

§6.3.2.1 ¶1 (Lvalues, arrays, and function designators)

An lvalue is an expression with an object type or an incomplete type other than void; ...

So as a result it's just like any other unary & with an lvalue.

like image 192
Flexo Avatar answered Oct 24 '22 18:10

Flexo