Is the completing of a structure type valid for all prior declarations of that type at the same scope?

Viewed 76

The standard states first (emphasize mine):

"An array type of unknown size is an incomplete type. It is completed, for an identifier of that type,by specifying the size in a later declaration (with internal or external linkage). A structure or union type of unknown content (as described in 6.7.2.3) is an incomplete type. It is completed, for all declarations of that type, by declaring the same structure or union tag with its defining content later in the same scope."

Source: C18, §6.2.5/22

but then later it states (emphasize mine):

"All declarations of structure, union, or enumerated types that have the same scope and use the same tag declare the same type. Irrespective of whether there is a tag or what other declarations of the type are in the same translation unit, the type is incomplete132) until immediately after the closing brace of the list defining the content, and complete thereafter.


132) An incomplete type can only be used when the size of an object of that type is not needed. It is not needed, for example, when a typedef name is declared to be a specifier for a structure or union, or when a pointer to or a function returning a structure or union is being declared. (See incomplete types in 6.2.5.) The specification has to be complete before such a function is called or defined."

Source: C18, §6.7.2.3/4

Isn't there a contradiction?

First it says, that the later completed declaration of a structure is valid for all declarations of that type, including the prior ones. Thus, a prior declaration shall IMHO denote a complete structure type.

But then it later says, that the completing of the type is only effective after the closing brace of the list defining the content at the defining declaration.

  • What is now right?

Testing at an Example:

#include <stdio.h>

struct foo;                           // prior declaration of struct foo.

int main (void)
{
    struct foo bar;
    //printf("%zu", sizeof(bar));
}

struct foo {                          // declaration of foo with defined content.
    int x;
    char y[4];
};

The compiler throw an error when compiling this code:

GCC:

"7:16: error: storage size of 'bar' isn't known"

Clang:

"7:16: error: variable has incomplete type 'struct foo'"

Evidence


Thus, it seems that they are implemented to follow the latter quote.

  • But isn't that wrong or at least not strictly standard-compliant/correct since the standards says that the completing of the structure type at a later declaration should be valid for the prior one when in the same scope?

Reasoning with quotes of the standard is highly appreciated.

1 Answers

I do not see any contradiction.

First it says, that the later completed declaration of a structure is valid for all declarations of that type, including the prior ones. Thus, a prior declaration shall IMHO denote a complete structure type.

Prior declarations do not denote a complete type. The type becomes complete only after the point of a definition of the structure.

Consider the following example

#include <stdio.h>

struct A;

int main(void) 
{
//  printf( "sizeof( struct A ) = %zu\n", sizeof( struct A ) );

    extern struct A { int x; } a;

    printf( "sizeof( struct A ) = %zu\n", sizeof( a ) );
    
    return 0;
}

If to uncomment the first call of printf the compiler will issue an error because in this point the definition of the structure A is unknown.

Related