c++ - typedef 声明中的 typedef-name 是可选的吗?

标签 c++ c typedef

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

typedef enum test { one };

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

typedef enum test { one } test;

如前所述,g++-4.2 甚至在没有警告的情况下接受它。 Clang++ 3.0 警告“warning: typedef requires a name”,类似地 Comeau 警告“warning: declaration requires a typedef name”,g++-4.6 通知:“warning : 'typedef' 在此声明中被忽略"。

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

更新:我使用相同的编译器检查了 C。 Clang 和 Comeau 产生相同的输出,gcc 给出警告:“warning: useless storage class specifier in empty declaration”,这似乎更令人困惑。

更新:我检查了删除枚举的名称,结果是一样的:

typedef enum { one };

与命名结构类似:

typedef struct named { int x };

但不是使用未命名的结构,在这种情况下,代码在 g++ (4.2/4.6) 中被拒绝,并显示“error: missing type-name in typedef-declaration”, gcc (4.2/4.6 ) 给出警告:“警告:未定义实例的未命名结构/union ”,clang++“警告:声明未声明任何内容”,comeau“错误:声明需要一个 typedef 名称"

最佳答案

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

enum test { one };

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

typedef struct SomeThing { int whatever; };

这相当于:

struct SomeThing { int whatever; };

请注意,typedef 正式(或语法上)是“存储类说明符”,如 staticexternauto注册.


C 标准

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

§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

并且(根据要求):

§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。所以,C++中typedef的语法规范肯定与C规范不同。

§7 Declarations

声明指定如何解释名称。声明的格式为

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


由于 §7 ¶5 说 typedef 名称来自 init-declarator 并且 init-declarator-list 被标记为 '< em>opt',我认为这意味着 typedef 名称在 C++ 中可以省略,就像在 C 中一样。

关于c++ - typedef 声明中的 typedef-name 是可选的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6399898/

相关文章:

c++ - Typedeffing 函数(不是函数指针)

c# - `using` 作为 typedef 导致 CS1001

c++逐列构造矩阵读取列

c++ - 如何在 Qt 中进行 MySQL 查询?

objective-c - 升级到 Xcode 7.3 swift 2.2 后,从 swift 调用 obj-c 枚举不起作用

c - 使用 malloc() 和 free() 指针可能导致内存泄漏,以及与指针表示法混淆

c - 我的阵列的类型是什么?

c++ - 如何获取字符串 vector 中某个元素的位置,将其用作整数 vector 中的索引?

c++ - 在 LLVM 中生成函数指针

c - 具有多个数组的结构,其大小在执行时定义