简体   繁体   中英

Can a structure tag be used before its scope?

In the following example:

#include <stdio.h>
#include <stdlib.h>

struct B b;
struct B{int a;}; 

struct B;

int main()
{
    b.a=3;
    printf("%d\n", b.a);
    return 0;
}

The file scope of structure tag B starts from its first definition/declaration struct B{int a;}; . How can struct B b; refer to B before B 's scope without error?

Is struct B; a structure type declaration, or a structure type definition? Why does it not conflict with the other definition struct B{int a;}; in the same file scope?

struct B; is a structure declaration . There can be any number of declarations of the same object. For the kinds of objects that have multiple possible declarations, the declarations have to be compatible — for example you can have multiple prototypes for the same function, but they need to use the same argument and return types. For a structure, there's only one way to declare it without defining it, and it just says “there's a structure called B ”. So it's ok to repeat struct B; as many times as you want.

struct B{int a;}; is a structure definition . There can only be one definition of a given object. Certain uses of an object require a prior definition, others only require a prior declaration. For example, you can define a variable whose type is a pointer to an undefined structure:

struct S;
struct S *p = NULL;

But you can't define a variable whose type is an undefined structure:

struct S;
struct S s = {0};

The reason for this difference is that a structure that hasn't been defined yet is an incomplete type — a type for which the compiler doesn't have a size. This isn't a problem to define a pointer, but it is a problem to define an object of the incomplete type: the compiler wouldn't know how much memory is required.

At this point, you may wonder why struct B b; is OK. After all, struct B hasn't even been declared, let alone defined.

The first part of why it's ok is that struct B b; declares the structure B in passing. So by the time struct B is needed to do something with b , the structure has just been declared.

The second part of why it's ok is that struct B b; is not exactly a definition. If it was a definition, then the compiler would need to know how much space to reserve, and an incomplete type would not be ok. This is what would happen if the variable was defined in a function:

void f(void) {
    struct B b; // error: storage size of ‘b’ isn’t known
}

But when struct B b; is at the top level of a file, it's a tentative definition . A tentative definition is a declaration; for this, the structure doesn't need to have been defined. When the compiler gets to the end of the file, any tentative definition that hasn't had a proper definition, and for which a definition is needed, becomes a definition. At this point, the structure needs to have been defined. In your example program, b has a tentative definition, and that definition becomes a proper definition at the end of the file.

It's ok to not define the structure if the variable is unused, because it's ok to declare a variable with an incomplete type if the variable is not used.

struct B b;
// end of file

But if the variable is used in a way that requires a complete type, then the structure must have been defined at that point.

struct B b;
void f(void) {
    sizeof(b); // error: invalid application of ‘sizeof’ to incomplete type ‘struct B’
}
struct B{int a;}; // too late

Question: How can struct B b; refer to B before B's scope without error? Answer: From http://c0x.coding-guidelines.com/6.7.2.3.html in section 1471, "If a type specifier of the form struct-or-union identifier occurs other than as part of one of the above forms, and no other declaration of the identifier as a tag is visible, then it declares an incomplete structure or union type, and declares the identifier as the tag of that type."
So, you can use the struct tag as forward declaration before the struct type definition.

Question: Is struct B; a structure type declaration, or a structure type definition? Why does it not conflict with the other definition struct B{int a;}; in the same file scope? Answer: From the same above link in section 1472, "If a type specifier of the form struct-or-union identifier or enum identifier occurs other than as part of one of the above forms, and a declaration of the identifier as a tag is visible, then it specifies the same type as that other declaration, and does not redeclare the tag."

struct B; is a structure type declaration, struct B{int a;}; is a structure type definition and that's how they do not conflict each other. You may choose to use the typedef to get rid of the confusion and show more visibility into your structure declaration:

typedef struct B B;
struct B{
    int a;
}; 
B b;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM