`typedef struct foo {int bar};`的合法性

Dav*_*men 6 c struct typedef language-lawyer

这个问题来自问题是结构{...}; 一个类型或一个未命名的变量?

在那个问题上,OP询问了一下

typedef struct student_s {
    char* name;
    int age;
    double height;
    struct student_s* next;   
};
Run Code Online (Sandbox Code Playgroud)

我问的是上述的合法性.编译包含上述代码的代码时,是否需要诊断(或使其更简单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.

以上推理是否正确?

Ser*_*sta 2

6.7.1 存储类说明符定义typedef为带有以下注释的存储类说明符:typedef 说明符称为 \xe2\x80\x98\xe2\x80\x98存储类说明符\xe2\x80\x99\xe2\x80\x99仅是为了语法方便;

\n\n

6.7 声明包含:

\n\n

句法:

\n\n
    \n
  • 声明:\n\n
      \n
    • 声明说明符 init-declarator-list opt
    • \n
  • \n
  • 声明说明符:\n\n
      \n
    • 存储类说明符声明说明符opt
    • \n
    • 类型说明符声明说明符opt
    • \n
    • 类型限定符声明说明符opt
    • \n
    • 函数说明符声明说明符opt
    • \n
  • \n
  • 初始化声明符列表:\n\n
      \n
    • 初始化声明符
    • \n
    • 初始化声明符列表, 初始化声明符
    • \n
  • \n
  • 初始化声明符:\n\n
      \n
    • 声明者
    • \n
    • 声明器 = 初始化器
    • \n
  • \n
\n\n

第一个约束是:声明应至少声明一个声明符(函数的参数或结构或联合的成员除外)、标签或枚举的成员

\n\n

由于 init-declarator-list 在声明中是可选的,只要声明了声明器或标记,我会说这typedef struct foo {int bar;};是一个分解为storage-class-specifier type-specifier没有 init-declarator 的声明。但由于类型说明符在内部声明了一个标记 ( foo),因此遵守了约束。

\n\n

我的结论是,这样的构造是有效的,并且只会对编译器产生警告。

\n