首页 文章

typedef声明中的typedef-name是否可选?

提问于
浏览
32

当我看到下面的代码在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 回答

  • 41

    它是一种允许退化的语法,但没有任何好处 . 大多数现代编译器可能会被激怒而发出警告;默认情况下,他们可能不会 . 没有typedef名称,关键字 typedef 是多余的;在您的示例中,它完全等同于:

    enum test { one };
    

    可能发生的另一个地方是结构:

    typedef struct SomeThing { int whatever; };
    

    这相当于:

    struct SomeThing { int whatever; };
    

    请注意 typedef 正式(或语法上)'storage class specifier',如 staticexternautoregister .


    C标准

    在ISO / IEC 9899:1999(即C标准)中,我们发现:

    §6.7声明语法声明:declaration-specifiers init-declarator-listopt; declaration-specifiers:storage-class-specifier declaration-specifiersopt type-specifier declaration-specifiersopt type-qualifier declaration-specifiersopt function-specifier declaration-specifiersopt init-declarator-list:init-declarator init-declarator-list,init-declarator init- declarator:declarator declarator = initializer

    并(根据要求):

    §6.7.1存储类说明符语法storage-class-specifier:typedef extern static auto register

    如果你追踪这种语法,就会有很多退化的可能性,你所展示的只是其中之一 .


    C标准

    C可能有不同的规则 .

    在ISO / IEC 14882:1998(原始C标准)中,我们在§7.1.1'Storage class specifiers'中发现C不将 typedef 视为存储类;该列表添加 mutable 并排除 typedef . 因此,C中 typedef 的语法规范肯定不同于C规范 .

    §7声明

    声明指定如何解释名称 . 声明有形式

    declaration-seq:声明声明-seq声明声明:block-declaration函数定义template-declaration显式实例化explicit-specialization linkage-specification命名空间定义block-declaration:simple-declaration asm-definition namespace-alias-definition using-声明using-directive simple-declaration:decl-specifier-seqopt init-declarator-listopt; ...¶5如果decl-specifier-seq包含typedef说明符,则声明称为typedef声明,并且每个init-declarator的名称声明为typedef-name,与其关联类型同义(7.1.3 ) . §7.1说明符[dcl.spec]可以在声明中使用的说明符是decl-specifier:storage-class-specifier type-specifier function-specifier friend typedef decl-specifier-seq:decl-specifier-seqopt decl-specifier§ 7.1.1存储类说明符[dcl.stc] storage-class-specifier:auto register static externmutable§7.1.2函数说明符[dcl.fct.spec] function-specifier:inline virtualexplicit§7.1.3typedef说明符[ dcl.typedef]包含decl-specifier typedef的声明声明了以后可用于命名基本(3.9.1)或复合(3.9.2)类型的标识符 . typedef说明符不应在函数定义(8.4)中使用,并且除了类型说明符之外,它不应在decl-specifier-seq中与任何其他类型的说明符组合 . typedef-name:identifier ...在给定范围内,typedef说明符可用于重新定义在该范围内声明的任何类型的名称,以引用它已引用的类型 . [例如:typedef struct s {/ * ... * /} s;
    typedef int I;
    typedef int I;
    typedef我;
    -end example]§7.1.4朋友说明符[dcl.friend]朋友说明符用于指定对类成员的访问;见11.4 . §7.1.5类型说明符[dcl.type] type-specifier:simple-type-specifier class-specifier enum-specifier elaborated-type-specifier cv-qualifier


    由于§7¶5表示 typedef 名称来自init-declarator而init-declarator-list被标记为'opt',我认为这意味着 typedef 名称可以在C中省略,就像在C中一样 .

  • 3

    我唯一能找到的是C 03标准_698269中的以下内容:

    typedef-name:identifier使用typedef说明符声明的名称将成为typedef-name .

    注意缺少的opt after标识符,它至少向我表明typedef-name需要一个标识符 . 奇怪的是,所有经过测试的编译器(默默地)接受这一点 .


    Edit :在@ Jonathan回答之后,我发现以下标准与上述相同:

    decl-specifier:storage-class-specifier type-specifier function-specifier friend typedef

    可以看出,它为 typedef 提供了一个额外的案例,存储类说明符上的列表证实了这一点:

    storage-class-specifier:auto register static extern mutable

    所以,在C案例中,我们和以前一样无能为力 .

  • 0

    对我来说,它看起来真的像C与C的区别 . C隐式地为其标签键入结构和联合;所以添加typedef是多余的,但不是错误 . 我不知道这是否适用于枚举 .

    接下来要做的是查看这些声明后允许的变量定义 .

    enum test etest;
    test etest2;
    struct named snamed;
    named snamed2;
    

相关问题