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

Dav*_*eas 34 c c++ typedef

当我在g ++ - 4.2中看到以下代码编译没有错误或警告时,我感到非常惊讶:

typedef enum test { one };
Run Code Online (Sandbox Code Playgroud)

我的假设是,如果您使用typedef关键字,则需要额外的标识符,如:

typedef enum test { one } test;
Run Code Online (Sandbox Code Playgroud)

如前所述,g ++ - 4.2在没有警告的情况下接受它.Clang ++ 3.0警告" 警告:typedef需要一个名字 ",类似的Comeau警告" 警告:声明需要一个typedef名称 ",并且g ++ - 4.6通知:" 警告:'typedef'在此声明中被忽略 ".

我无法确定标准中允许的位置,并且我发现有两个编译器警告它是必需的,这有点令人困惑,如果typedef-name是必需的但不存在则不应该是错误吗?

更新:我用相同的编译器检查了C.Clang和comeau产生相同的输出,gcc发出警告:" 警告:空声明中无用的存储类说明符 ",这看起来更令人困惑.

更新:我已检查删除枚举的名称,结果是相同的:

typedef enum { one };
Run Code Online (Sandbox Code Playgroud)

与命名结构类似:

typedef struct named { int x };
Run Code Online (Sandbox Code Playgroud)

但是没有一个未命名的结构,在这种情况下,代码在g ++(4.2/4.6)中被拒绝" 错误:在typedef-declaration中缺少type-name ",gcc(4.2/4.6)发出警告:" warning:unnamed struct/union定义没有实例 ",clang ++" 警告:声明没有声明任何 ",comeau" 错误:声明需要typedef名称 "

Jon*_*ler 43

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

enum test { one };
Run Code Online (Sandbox Code Playgroud)

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

typedef struct SomeThing { int whatever; };
Run Code Online (Sandbox Code Playgroud)

这相当于:

struct SomeThing { int whatever; };
Run Code Online (Sandbox Code Playgroud)

需要注意的是typedef正式(或语法)一个"存储类说明",如static,extern,autoregister.


C标准

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

§6.7声明

句法

声明:

declaration-specifiers init-declarator-listopt;

declaration-specifiers:

存储类说明符 声明,符选择

type-specifier declaration-specifiersopt

type-qualifier 声明 - 说明符opt

function-specifier declaration-specifiersopt

init-declarator-list:

初始化声明符

init-declarator-list , init-declarator

init-declarator:

声明符

declarator = initializer

And (as requested):

§6.7.1 Storage-class specifiers

Syntax

storage-class-specifier:

typedef

extern

static

auto

register

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


C++标准

C++可能有不同的规则.

在ISO/IEC 14882:1998(最初的C++标准)中,我们在§7.1.1"存储类说明符"中发现C++不将其typedef视为存储类; 列表添加mutable和排除typedef.因此,typedefC++中的语法规范肯定不同于C规范.

§7声明

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

声明-SEQ:

declaration

声明-seq声明

宣言:

block-declaration

函数的定义

template-declaration

显式实例化

explicit-specialization

联动规范

namespace-definition

block-declaration:

简单的声明

asm-definition

命名空间别名定义

using-declaration

使用指示符

简单的声明:

decl-specifier-seqopt init-declarator-listopt ;

...

¶5 If the decl-specifier-seq contains the typedef符,则声明称为typedef声明,声明每个声明的名称为init-declarator typedef-name,与其关联类型(7.1.3)同义.

§7.1说明符[dcl.spec]

可以在声明中使用的说明符是

DECL说明符:

storage-class-specifier

类型说明符

function-specifier

friend

typedef

DECL说明符-SEQ:

decl-specifier-seqopt

DECL说明符

§7.1.1存储类说明符[dcl.stc]

存储类说明符:

auto

register

static

extern

mutable

§7.1.2函数说明符[dcl.fct.spec]

功能说明符:

inline

virtual

explicit

§7.1.3typedef说明符[dcl.typedef]

包含decl-specifier的 typedef声明声明了以后可用于命名基本(3.9.1)或复合(3.9.2)类型的标识符.该typedef说明符不应在函数定义(8.4)中使用,并且除了类型说明符之外,它不应与除了类型说明符之外的任何其他类型的说明符组合在一个decl-specifier-seq中.

typedef的名称:

identifier

...

In a given scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers. [Example:

typedef struct s { /* ... */ } s;
typedef int I;
typedef int I;
typedef I I;
Run Code Online (Sandbox Code Playgroud)

—end example]

§7.1.4 The friend specifier [dcl.friend]

The friend specifier is used to specify access to class members; see 11.4.

§7.1.5 Type specifiers [dcl.type]

type-specifier:

简单型说明符

class-specifier

枚举符

elaborated-type-specifier

CV-预选赛


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

  • @David似乎是GCC中的一个错误.如果decl-specifier-seq没有在翻译单元中引入任何名称,那么它只是C++中的错误.似乎GCC假定任何枚举都有枚举器并将其声明为名称.但是对于一个空的枚举,当然这种假设并不成立. (2认同)