`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] 

所以语法是可以接受的,但没有声明者,代码就是垃圾