当我在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
,auto
和register
.
在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++可能有不同的规则.
在ISO/IEC 14882:1998(最初的C++标准)中,我们在§7.1.1"存储类说明符"中发现C++不将其typedef
视为存储类; 列表添加mutable
和排除typedef
.因此,typedef
C++中的语法规范肯定不同于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:
Run Code Online (Sandbox Code Playgroud)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:
简单型说明符
class-specifier
枚举符
elaborated-type-specifier
CV-预选赛
由于§75表示typedef
名称来自init-declarator而init-declarator-list被标记为' opt ',我认为这意味着该typedef
名称可以在C++中省略,就像在C中一样.