当我看到下面的代码在g -4.2中编译没有错误或警告时,我感到非常惊讶:
typedef enum test { one };
我的假设是,如果您使用 typedef
关键字,则需要额外的标识符,如:
typedef enum test { one } test;
如前所述,g -4.2甚至没有警告也接受它 . Clang 3.0警告“警告:typedef需要一个名称", similarly Comeau warns "警告:声明需要一个typedef名称", and g++-4.6 informs: "警告:'typedef'在此声明中被忽略” .
我无法确定标准中允许的位置,并且我发现两个编译器警告它是必需的,这有点令人困惑,如果typedef-name是必需的但不存在则不应该是错误吗?
UPDATE :我在C中使用相同的编译器进行了检查 . Clang和comeau产生相同的输出,gcc发出警告:“警告:空声明中无用的存储类说明符”,这似乎更令人困惑 .
UPDATE :我已经检查过删除枚举的名称,结果是一样的:
typedef enum { one };
与命名结构类似:
typedef struct named { int x };
但是没有一个未命名的结构,在这种情况下,代码在g(4.2 / 4.6)中被拒绝“错误:在typedef-declaration中缺少type-name ", gcc (4.2/4.6) gave a warning: "警告:未命名的struct / union定义没有实例", clang++ " warning:声明不声明任何内容", comeau "错误:声明需要typedef名称“
3 回答
它是一种允许退化的语法,但没有任何好处 . 大多数现代编译器可能会被激怒而发出警告;默认情况下,他们可能不会 . 没有typedef名称,关键字
typedef
是多余的;在您的示例中,它完全等同于:可能发生的另一个地方是结构:
这相当于:
请注意
typedef
正式(或语法上)'storage class specifier',如static
,extern
,auto
和register
.C标准
在ISO / IEC 9899:1999(即C标准)中,我们发现:
并(根据要求):
如果你追踪这种语法,就会有很多退化的可能性,你所展示的只是其中之一 .
C标准
C可能有不同的规则 .
在ISO / IEC 14882:1998(原始C标准)中,我们在§7.1.1'Storage class specifiers'中发现C不将
typedef
视为存储类;该列表添加mutable
并排除typedef
. 因此,C中typedef
的语法规范肯定不同于C规范 .声明指定如何解释名称 . 声明有形式
由于§7¶5表示
typedef
名称来自init-declarator而init-declarator-list被标记为'opt',我认为这意味着typedef
名称可以在C中省略,就像在C中一样 .我唯一能找到的是C 03标准_698269中的以下内容:
注意缺少的opt after标识符,它至少向我表明typedef-name需要一个标识符 . 奇怪的是,所有经过测试的编译器(默默地)接受这一点 .
Edit :在@ Jonathan回答之后,我发现以下标准与上述相同:
可以看出,它为
typedef
提供了一个额外的案例,存储类说明符上的列表证实了这一点:所以,在C案例中,我们和以前一样无能为力 .
对我来说,它看起来真的像C与C的区别 . C隐式地为其标签键入结构和联合;所以添加typedef是多余的,但不是错误 . 我不知道这是否适用于枚举 .
接下来要做的是查看这些声明后允许的变量定义 .