Search code examples
cstructtypesstructuredefinition

Why a structure containing a struct pointer member compile but containing a simple struct member does not compile


While learning about structures in c language I am confused that why the following code does not compile.

#include <iostream>
struct data{
    int a;
    int b;
    struct data c;
};

typedef struct data data_t;

int main()
{
    data_t mydata = {1,2,{3,4}};
    std::cout << mydata.a;

    return 0;
}

But this code compiles without any error.

#include <iostream>
struct data{
    int a;
    int b;
    struct data *c;
};

typedef struct data data_t;

int main()
{
    data_t mydata = {1,2,&mydata};
    std::cout << (*mydata.c).a;
    return 0;
}

Solution

  • A structure is a complete type after the closing brace.

    From the C Standard (6.7.2.1 Structure and union specifiers)

    8 The presence of a struct-declaration-list in a struct-or-union-specifier declares a new type, within a translation unit. The struct-declaration-list is a sequence of declarations for the members of the structure or union. If the struct-declaration-list contains no named members, no anonymous structures, and no anonymous unions, the behavior is undefined. The type is incomplete until immediately after the } that terminates the list, and complete thereafter.

    Or from the C++ 14 Standard (9.2 Class members)

    2 A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, using-declarations introducing inheriting constructors (12.9), exception-specifications, and brace-or-equal-initializer s for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.

    So in this declaration

    struct data{
        int a;
        int b;
        struct data c;
    };
    

    where the data member c is declared the structure is not yet a complete type. So the compiler does not know what is the size of the data member c. So the compiler is unable to generate the definition of the structure.

    From the C Standard (6.2.5 Types)

    1. ... At various points within a translation unit an object type may be incomplete (lacking sufficient information to determine the size of objects of that type) or complete (having sufficient information).

    On the other hand, pointers are always complete types. Their sizes are always known.

    From the C Standard (6.2.5 Types)

    — A pointer type may be derived from a function type or an object type, called the referenced type. A pointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type T is sometimes called ‘‘pointer to T’’. The construction of a pointer type from a referenced type is called ‘‘pointer type derivation’’. A pointer type is a complete object type.

    Pay attention to that your programs are not C programs because C does not have the header <iostream>. You showed C++ programs.

    Nevertheless the quotes I provided are valid also for C++.