Is a struct {…}; a type or an unnamed variable?

…衆ロ難τιáo~ 提交于 2019-12-30 09:06:37

问题


Is the following, at file scope, a type declaration or an unnamed variable?

struct student_s {
    char* name;
    int age;
    double height;
    struct student_s* next;   
};

If it is a type definition, then what is the difference with:

typedef struct student_s {
    char* name;
    int age;
    double height;
    struct student_s* next;   
};

?

(Background: see my answer at Changing a variable from global to local - C, where I believe the first introduces an unnamed variable that is then optimized away by the compiler.)

Note: the question has been flagged as a possible duplicate of In what scope is a struct member identifier put? but I believe I am not asking a question about the scope of the members but about what the declarations actually create. However. answers to Difference between 'struct' and 'typedef struct' in C++? do explain my question.


回答1:


As per the C standard, a structure declaration in the form like

struct student_s {
    char* name;
    int age;
    double height;
    struct student_s* next;   
};

is the declaration of a type. Quoting C11, chapter §6.7.2.1

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. [...]

C standard does not mandate creating a variable (either named or unnamed) for that type.

In your second snippet, you actually (try to) typedef to nothing. However, if you change your snippet to the form of

typedef struct {
         //.....members
} student_s ;

you'll be creating a type student_s (typedef to an unnamed structure type) which you can use later.

FWIW, we never talked about a variable being created here, anyways. It's all about types.




回答2:


First declaration declares a type. After that declaration, the type struct student_s is known, and you can declare variables of that type or pointer to it :

struct student_s student1;
struct student_s *pStudent;

The second declaration is weird even if is compiles. The common usage would be :

typedef struct {
    char* name;
    int age;
    double height;
    struct student_s* next;   
} studend_t;

which declares an alias student_t to an anonymous struct. It can then be used directly :

student_t student1;
student_t *pStudent;

BUT THE SECOND EXAMPLE DOES COMPILE (even with a warning) AND IS THE SAME AS FIRST ONE !

What it really does is to declare a void alias to struct student_s. The typedef is ignored and produces a warning : typedef requires a name, but as a side effect, the struct is declared, exactly as it was in first example.

So the true answer to the actual question is THERE ARE NO DIFFERENCES except for a warning.




回答3:


Both are type definitions. The second one is one incomplete. It doesn't supply a name as the the argument of typedef. Much better is to use

typedef struct student_s {
    char* name;
    int age;
    double height;
    struct student_s* next;   
} student;


Regarding the legality of

typedef struct student_s {
    char* name;
    int age;
    double height;
    struct student_s* next;   
};

I've asked that as a separate question, Legality of `typedef struct foo {int bar};`




回答4:


It's a type, and you can't have an anonymous instance of a struct. For comparison, this declares both the type struct_type and an instance struct_instance of that type:

struct struct_type {
    /* blah */
} struct_instance;

If you wanted to declare another instance in isolation (from the type decl) you'd use

struct struct_type another_instance;

The use of typedef - if done correctly, unlike your example - just allows you to give the type another name which doesn't require the struct keyword to declare an instance:

typedef struct_type MyStruct;
MyStruct yet_another_instance;

or equivalently

typedef struct struct_type {
    /* blah */
} MyStruct;

omitting the name (struct_type) gives you an anonymous struct type which can only referred to by its typedef'd name.


Note 1

Since your original struct contains a next pointer to its own type, that type must have a name at the point the member is declared. So, you cannot declare an anonymous struct with a self-typed pointer. If you give your anonymous struct type a name with typedef, that name doesn't exist until after the member declaration, so can't be used there.

typedef struct /*S*/ {
    struct S *next; /* T doesn't exist yet, so without S, you can't declare this */
} T;

Note 2

You can declare an anonymous instance of an anonymous union, as a member:

struct S {
    union {
        int i;
        unsigned u;
    };
};

struct S s;
s.i = -1;
printf("%x\n", s.u);

but that's a very special case. I took the remark about this out of the main argument, in case it was misleading.




回答5:


struct A { ... }

creates struct 'A' visible in struct namespace (which has nothing common with C++ namespaces). So, to access struct you have to use struct keyword;

struct A a;

When defined with typedef struct

typedef struct A { ... } B;

becomes visible and bound to B, and you can easily create struct like common variable of type B

B a;

Please, correct me someone, if I am wrong.




回答6:


The difference is that with the first example, you have to declare a new variable like this: struct student_s variable;, however with the second example, you may simply do student_s variable;.



来源:https://stackoverflow.com/questions/31877661/is-a-struct-a-type-or-an-unnamed-variable

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!