Home > Software design >  C pointer to incomplete struct type and later struct type completion VS. pointer to undeclared type
C pointer to incomplete struct type and later struct type completion VS. pointer to undeclared type

Time:07-06

The following is a legal fragment in C:

/* Example 1. */

struct B *p; /* p: pointer to incomplete struct type B */

/* This declaration completes the struct type B. */
struct B {
    int foo;
};

As long as no pointer operations are performed on p (e.g. p ) until complete type information for struct type B is provided, the fragment is legal C.

On the other hand, the next fragment is illegal in C:

/* Example 2. */

T_t *p; /* p: pointer to undeclared type T_t. */

typedef int T_t;

Question: What is the reason that it is legal in C to declare a pointer to an incomplete struct type and provide the complete struct type information later (Example 1), whereas it is illegal to declare a pointer to an undeclared type and declare the type later (Example 2)?

CodePudding user response:

Because of the struct keyword, it is known what kind of entity struct B refers to, even before struct B is declared. It is a type --- a struct type, to be more precise. It is an incomplete type, because the declaration of struct B has not been seen yet. But for some uses, such as declaring a pointer, it is sufficient.

On the other hand it is not known what T_t is. Is it a type? Is it a variable? Is it a function? Is it an enumerator? If it is a type, we are OK. If it is not, this declaration either makes no sense, or worse, has more than one meaning depending on what T_t is.

The C language is defined in such a way that the compiler does not need to look ahead much. It reads from top to bottom and decides on the spot. Can T_t *p; be interpreted unambiguously based on what is already seen? If not, then it is invalid.

CodePudding user response:

Types with "tags" (struct, union, enum) have special rules (c17 6.7.2.3):

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 incomplete until immediately after the closing brace of the list defining the content, and complete thereafter.

This allows for forward declaration of an incomplete type which will later be completed. In case of structs there are some useful applications for this feature: it allows self-referencing structs (like linked list nodes) and it allows private encapsulation in the form of "opaque types", where the struct definition is hidden outside the translation unit.

  • Related