这个问题来自问题Is a struct {...}; a type or an unnamed variable?
在那个问题上,OP询问了
typedef struct student_s {
char* name;
int age;
double height;
struct student_s* next;
};
我在问上述合法性。编译包含上述代码的代码时是否需要诊断(或使其更简单,typedef struct foo {int bar;};
)?
我认为,从语言律师的角度来看,不需要诊断是合法的。 (旁白:我不主张使用它。它非常值得诊断。如果我错误地编写了类似上面的代码,我非常希望编译器警告我。)
C11标准的第6.7节规定了声明的语法: declaration-specifiers init-declarator-list opt ;
注意 init-declarator -list 是可选的。这可能导致人们认为typedef int;
有效。这不是因为标准也说
除static_assert声明之外的声明应至少声明一个声明符(除了函数的参数或结构或联合的成员),标记或枚举的成员。
因此typedef int;
和typedef struct {int bar};
是非法的,因为它们不声明声明符,标记或枚举成员。
另一方面,在我看来typedef struct foo {int bar;};
是合法的,因为它确实声明了一些东西。特别是,它声明并定义了struct
标记foo
。
上述推理是否正确?
答案 0 :(得分:2)
在你引用的引文中,有人声称声明应在其他方面声明标签。
所以这个宣言
typedef struct student_s {
char* name;
int age;
double height;
struct student_s* next;
};
简单地声明struct student_s
并且等同于没有typedef说明符的声明
struct student_s {
char* name;
int age;
double height;
struct student_s* next;
};
它没有在范围中引入typedef名称。
答案 1 :(得分:1)
6.7.1存储类说明符将typedef
定义为具有以下注释的存储类说明符: typedef说明符称为“存储类说明符”,以方便语法
仅;
6.7声明包含:
语法:
第一个约束是:声明应至少声明一个声明者 (除了函数的参数或 结构或联合的成员),标记或枚举的成员
由于init-declarator-list在声明中是可选的,如果声明了声明符或标记,我会说typedef struct foo {int bar;};
是一个声明被分解为storage-class-specifier type-specifier
而没有init-declarator的声明。但是,由于类型说明符在内部声明了一个标记(foo
),因此尊重该约束。
我的结论是这样的构造是有效的,只会在编译器上产生警告。
答案 2 :(得分:0)
此typedef:
typedef struct student_s {
char* name;
int age;
double height;
struct student_s* next;
};
产生以下结果:
warning useless storage class specifier in empty declaration [enabled by default]
所以语法是可以接受的,但没有声明者,代码就是垃圾