是的typedef名可选的typedef声明? [英] Is the typedef-name optional in a typedef declaration?
问题描述
我很惊讶,当我看到下面的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 ++中被省略,只是在CI 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', likestatic
,extern
,auto
andregister
.
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 addsmutable
and excludestypedef
. So, the grammatical specification oftypedef
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 atypedef
declaration and the name of eachinit-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. Thetypedef
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 thetypedef
name can be omitted in C++, just as in C.这篇关于是的typedef名可选的typedef声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!