这个问题来自于问题是struct{…};类型还是未命名的变量?
在那个问题中,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-listopt ;
注意init-declarator-list是可选的。这可能导致人们认为typedef int;
是有效的。不是因为标准还规定
除static_assert声明以外的声明至少应声明一个声明符(函数的形参、结构体或联合的成员除外)、一个标记或枚举的成员。
因此typedef int;
和typedef struct {int bar};
是非法的,因为它们没有声明声明符、标记或枚举成员。
typedef struct foo {int bar;};
是合法的,因为它确实声明了一些东西。特别地,它声明并定义了struct
标记foo
。
以上推理正确吗?
在你引用的这段引文中,有一段写着声明应该声明一个标签。
所以这个声明
typedef struct student_s {
char* name;
int age;
double height;
struct student_s* next;
};
简单地声明struct student_s
和等价于没有类型定义说明符的声明
struct student_s {
char* name;
int age;
double height;
struct student_s* next;
};
它没有在作用域中引入类型定义名。
6.7.1存储类说明符将typedef
定义为存储类说明符,并附有以下注释:为了语法方便,typedef说明符称为"存储类说明符",
和6.7声明包含:
语法:
- 声明:
- declaration-specifiers init-declarator-list <子>选择子>
- declaration-specifiers:
- storage-class-specifier declaration-specifiers <子>选择子>
- type-specifier declaration-specifiers <子>选择子>
- type-qualifier declaration-specifiers <子>选择子>
- function-specifier declaration-specifiers <子>选择子>
- init-declarator-list:
- init-declarator
- init-declarator-list, init-declarator
- init-declarator:
- 说明符
- 声明器=初始化器
第一个约束是:声明至少要声明一个声明器(除了函数的参数或结构或联合的成员、标记或枚举的成员
如果声明了声明器或标记,那么在声明中init-declarator-list是可选的,因此我认为typedef struct foo {int bar;};
是一个分解为没有init-declarator的storage-class-specifier type-specifier
的声明。但是,由于类型说明符在内部声明了一个标记(foo
),因此遵守了约束。
我的结论是,这样的构造是有效的,只会在编译器上产生警告。
this typepedef:
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]
所以语法是可以接受的,但是如果没有声明器,代码就是垃圾