`typedef struct foo {int bar};`的合法性
这个问题来自问题是结构{…}; 一个类型或一个未命名的变量?
在那个问题上,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;
已validation。 这不是因为标准也说明了这一点
除static_assert声明之外的声明应至少声明一个声明符(除函数的参数或结构或联合的成员之外),标记或枚举的成员。
因此typedef int;
和typedef struct {int bar};
是非法的,因为他们没有声明声明者,标签或枚举成员。
另一方面,在我看来, typedef struct foo {int bar;};
是合法的,因为它确实声明了一些东西。 特别是,它声明并定义了struct
标签foo
。
以上推理是否正确?
6.7.1存储类说明符将typedef
定义为具有以下注释的存储类说明符: typedef说明符被称为“存储类说明符”,仅用于语法方便;
6.7声明包含:
句法:
- 宣言:
- declaration-specifiers init-declarator-list opt
- 声明-符:
- 存储类说明符声明说明符选项
- type-specifier declaration-specifiers opt
- type-qualifier声明 – 说明符opt
- function-specifier declaration-specifiers opt
- 初始化声明符列表:
- 初始化声明符
- init-declarator-list,init-declarator
- 初始化声明符:
- 声明符
- declarator =初始化器
第一个约束是: 声明应至少声明一个声明符(除了函数的参数或结构或联合的成员),标记或枚举的成员
由于init-declarator-list在声明中是可选的,如果声明了声明符或标记,我会说typedef struct foo {int bar;};
是一个声明,它被分解为storage-class-specifier type-specifier
,没有init-declarator。 但是,由于类型说明符在内部声明了一个标记( foo
),因此该约束受到尊重。
我的结论是这样的构造是有效的,只会在编译器上产生警告。
在你引用的引文中写道,声明应在其他方面声明标签。
所以这个宣言
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名称。
这个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]
所以语法是可以接受的,但没有声明者,代码就是垃圾