是的typedef名可选的typedef声明? [英] Is the typedef-name optional in a typedef declaration?

查看:2530
本文介绍了是的typedef名可选的typedef声明?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很惊讶,当我看到下面的code没有错误或警告编译G ++ - 4.2:

 的typedef枚举{测试} 1;

我的假设是,如果你使用了的typedef 关键字,将需要一个额外的标识符为:

 的typedef枚举{测试} 1测试;

如已经提到的,克+ + - 4.2接受它,甚至没有一个警告。锵++ 3.0警告的警告:的typedef需要一个名称的,同样科莫警告的警告:申报需要一个typedef名称的,和g ++ - 4.6运筹学:警告:类型定义在这个声明被忽略

我没有在那里在标准允许这种能够确定,我觉得稍微混淆这两个编译器警告说,它的需要的,应该不会是一个错误,如果typedef的名称是的需要的而不是present?

更新:我已经用C检查使用相同的编译器。锵和科莫产生相同的输出,GCC发出警告:警告:在空声明无用的存储类说明的,这似乎更加混乱

更新:我已经检查删除枚举的名字,结果都是一样的:

 的typedef枚举{1};

同样与命名结构:

  typedef结构{名为INT X};

但不能与未命名的结构,在这种情况下,code的以g拒绝++(4.2 / 4.6)与错误:typedef的声明缺少类型名称的,海湾合作委员会( 4.2 / 4.6)给了一个警告:警告:无名结构/联合未定义任何实例的铛++的警告:申报不申报任何的科莫的错误:需要声明typedef名


解决方案

这是允许的,但不提供好处退化语法。大多数现代编译器能够挑起成发射一个关于它的警告;默认情况下,他们可能不会。如果没有typedef名称,关键字的typedef 是多余的;在你的例子,它是完全等效于:

 枚举测试{1};

在那里可以发生的另一个地方是一个结构:

  typedef结构{东西不管INT; };

这是等同于:

 结构的东西{INT什么; };

注意的typedef 正式(或语法)一个存储类说明,如静态的extern 汽车注册


C标准

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


  

§6.7声明


  
  

语法


  
  

声明的:


  
  

声明-符的init声明符列表 <子>选择;


  
  

声明-符的:


  
  

存储类说明符声明-符 <子>选择


  
  

类型说明符声明-符 <子>选择


  
  

类型限定符声明-符 <子>选择


  
  

函数说明符声明-符 <子>选择


  
  

的init声明符列表的:


  
  

的init声明符


  
  

的init声明符列表的init声明符


  
  

的init声明符的:


  
  

声明符


  
  

声明符的=的初始化


和(的要求):


  

§6.7.1存储类型修饰符


  
  

语法


  
  

存储类说明符:


  
  

的typedef


  
  

的extern


  
  

静态


  
  

汽车


  
  

注册


如果您通过跟踪该语法,有很多的退化可能性,你表现只是其中之一。


C ++标准

有可能的是C ++有不同的规则。

在ISO / IEC 14882:1998(原C ++标准),我们发现第7.1.1节存储类声明是C ++不把的typedef 作为存储类;列表中添加可变和排除的typedef 。因此,的typedef 的C ++语法规范是从C规格绝对不同的。


  

§7声明


声明指定名称如何被间preTED。声明的格式


  

声明-SEQ:


  
  

声明


  
  

声明-SEQ声明


  
  

声明:


  
  

块声明


  
  

函数定义


  
  

模板声明


  
  

显式实例


  
  

明确分工


  
  

联动规范


  
  

命名空间定义


  
  

块声明:


  
  

简单的声明


  
  

ASM-定义


  
  

命名空间的别名定义


  
  

using声明


  
  

using指令


  
  

简单的声明:


  
  

DECL说明符-SEQ 选择的init声明符列表选择;


  
  

...


  
  

¶5如果DECL说明符-SEQ
  包含的typedef 说明,声明被称为的typedef 申报
  每名的init声明符
  被声明为一个typedef名称,
  的代名词,其相关类型
  (7.1.3)。


  
  

§7.1说明符[dcl.spec]


  
  

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


  
  

DECL-说明:


  
  

存储类说明符


  
  

键入说明符


  
  

函数说明


  
  

朋友


  
  

的typedef


  
  

DECL说明符-SEQ:


  
  

DECL说明符-SEQ 选择


  
  

DECL说明符


  
  

第7.1.1节存储类说明[dcl.stc]


  
  

存储类说明符:


  
  

汽车


  
  

注册


  
  

静态


  
  

的extern


  
  

可变


  
  

§7.1.2功能说明符[dcl.fct.spec]


  
  

函数说明:


  
  

在线


  
  

虚拟


  
  

明确


  
  

§7.1.3的类型定义符[dcl.typedef]


  
  

包含DECL说明符声明
  的typedef 宣布,可以在以后的命名中使用的标识符
  基本(3.9.1)或化合物(3.9.2)的类型。在的typedef 说明不得在函数定义中使用
  (8.4),并且不得在DECL说明符-SEQ结合
  与任何其他种类的说明的除外
  一个类型说明符。


  
  

的typedef名称:


  
  

标识符


  
  

...


  
  

在一个给定的范围内,一个typedef符可以用来重新定义该范围内声明的任何类型的名称
  指其所已经提到的类型。 [示例:

 的typedef的struct {/ * ... * /}等;
的typedef诠释我;
的typedef诠释我;
我的typedef我;


  
  

末端示例]


  
  

§7.1.4的朋友符[dcl.friend]


  
  

这位朋友说明符用于指定访问类成员;见11.4。


  
  

§7.1.5类型说明符[dcl.type]


  
  

类型说明符:


  
  

简单类型说明符


  
  

类说明符


  
  

枚举符


  
  

阐述类型说明符


  
  

CV-预选赛



由于§7¶5说,的typedef 名来自的的init声明符的和的的init声明符列表被标记'的选择的',我认为这意味着的typedef 名称可以在C ++中被省略,只是在C

I was quite surprised when I saw the following code compile without errors or warnings in g++-4.2:

typedef enum test { one };

My assumption was that if you used the typedef keyword it would require an extra identifier as in:

typedef enum test { one } test;

As already mentioned, g++-4.2 accepts it without even a warning. Clang++ 3.0 warns "warning: typedef requires a name", similarly Comeau warns "warning: declaration requires a typedef name", and g++-4.6 informs: "warning: 'typedef' was ignored in this declaration".

I have not been able to identify where in the standard this is allowed, and I find it slightly confusing that two of the compilers warn that it is required, shouldn't it be an error if the typedef-name is required but not present?

UPDATE: I have checked in C with the same compilers. Clang and comeau yield the same output, gcc gives a warning: "warning: useless storage class specifier in empty declaration", which seems even more confusing.

UPDATE: I have checked removing the name of the enum and the results are the same:

typedef enum { one };

Similarly with a named struct:

typedef struct named { int x };

But not with an unnamed struct, in which case the code was rejected in g++ (4.2/4.6) with "error: missing type-name in typedef-declaration", gcc (4.2/4.6) gave a warning: "warning: unnamed struct/union that defines no instances", clang++ "warning: declaration does not declare anything", comeau "error: declaration requires a typedef name"

解决方案

It is a degenerate syntax that is allowed but provides no benefit. Most modern compilers can be provoked into emitting a warning about it; by default, they may not. Without the typedef name, the keyword typedef is superfluous; in your example, it is completely equivalent to:

enum test { one };

Another place where it can occur is with a structure:

typedef struct SomeThing { int whatever; };

This is equivalent to:

struct SomeThing { int whatever; };

Note that typedef is officially (or syntactically) a 'storage class specifier', like static, extern, auto and register.


C Standard

In ISO/IEC 9899:1999 (that's the C standard), we find:

§6.7 Declarations

Syntax

declaration:

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

And (as requested):

§6.7.1 Storage-class specifiers

Syntax

storage-class-specifier:

typedef

extern

static

auto

register

If you track through that syntax, there are a lot of degenerate possibilities, and what you showed is just one of the many.


C++ Standard

It is possible that C++ has different rules.

In ISO/IEC 14882:1998 (the original C++ standard), we find in §7.1.1 'Storage class specifiers' that C++ does not treat typedef as a storage class; the list adds mutable and excludes typedef. So, the grammatical specification of typedef in C++ is definitely different from the C specification.

§7 Declarations

Declarations specify how names are to be interpreted. Declarations have the form

declaration-seq:

declaration

declaration-seq declaration

declaration:

block-declaration

function-definition

template-declaration

explicit-instantiation

explicit-specialization

linkage-specification

namespace-definition

block-declaration:

simple-declaration

asm-definition

namespace-alias-definition

using-declaration

using-directive

simple-declaration:

decl-specifier-seqopt init-declarator-listopt ;

...

¶5 If the decl-specifier-seq contains the typedef specifier, the declaration is called a typedef declaration and the name of each init-declarator is declared to be a typedef-name, synonymous with its associated type (7.1.3).

§7.1 Specifiers [dcl.spec]

The specifiers that can be used in a declaration are

decl-specifier:

storage-class-specifier

type-specifier

function-specifier

friend

typedef

decl-specifier-seq:

decl-specifier-seqopt

decl-specifier

§7.1.1 Storage class specifiers [dcl.stc]

storage-class-specifier:

auto

register

static

extern

mutable

§7.1.2 Function specifiers [dcl.fct.spec]

function-specifier:

inline

virtual

explicit

§7.1.3 The typedef specifier [dcl.typedef]

Declarations containing the decl-specifier typedef declare identifiers that can be used later for naming fundamental (3.9.1) or compound (3.9.2) types. The typedef specifier shall not be used in a function-definition (8.4), and it shall not be combined in a decl-specifier-seq with any other kind of specifier except a type-specifier.

typedef-name:

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;

—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:

simple-type-specifier

class-specifier

enum-specifier

elaborated-type-specifier

cv-qualifier


Since §7 ¶5 says that typedef names come from the init-declarator and the init-declarator-list is tagged 'opt', I think that means that the typedef name can be omitted in C++, just as in C.

这篇关于是的typedef名可选的typedef声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆