以下段落取自[dcl.typedef]:
在其声明的范围内,typedef-name在语法上等同于关键字,并按照第8章中描述的方式命名与标识符关联的类型。因此,typedef-name是另一种类型的同义词。 typedef-name不会像类声明(9.1)或枚举声明那样引入新类型。
我们需要的另一个相关段落来自[dcl.type]
作为一般规则,在声明的完整decl-specifier-seq或类型说明符-seq或trailing-type-specifier-seq中最多允许一个类型说明符。此规则的唯一例外情况如下:... long可以与long结合使用。
在以下代码中,i1
只是long的同义词。
typedef long i1;
typedef long i1 i2;
因此,我希望第二行被理解为typedef long long i2
。但是,MSVC2015RC失败并带有
错误C2146语法错误:缺少';'在标识符'i2'之前
任何人都可以指出使我的期望无效的标准部分吗?
更新
我的观点是,据我所知,[dcl.type]中的语法,
type-specifier:
trailing-type-specifier
class-specifier
enum-specifier
trailing-type-specifier:
simple-type-specifier
elaborated-type-specifier
typename-specifier
cv-qualifier
type-specifier-seq:
type-specifier attribute-specifier-seq opt
type-specifier type-specifier-seq
trailing-type-specifier-seq:
trailing-type-specifier attribute-specifier-seq opt
trailing-type-specifier trailing-type-specifier-seq
decl-specifier-seq允许一系列类型说明符,只要它们满足组合规则即可。在我看来,类型与类型说明符不同,即使类型由类型说明符指定; - )
答案 0 :(得分:4)
好的,我会回答。
首先,看看这个:
typedef-name在语法上等同于关键字
这仅表示typedef-names遵循关键字的语法。这并不意味着typedef-name等同于任何特定关键字。它就像一个新的,独特的关键字。
然后我们有,
因此,typedef-name是另一种类型的同义词。
所以,鉴于typedef long i1;
,这是什么"另一种类型"?它是long int
,而不仅仅是long
。
此外,什么是"类型"?至少,类型说明符不是类型。类型说明符long
表示类型" long int" (参见n3337的表10或n4296的表9)。
我在这里复制我的评论:
i1
是类型的同义词long int
。它不是关键字long
的同义词。否则,您也可以说i1 double
并获得long double
。
虽然我应该说,i1
不是类型说明符 long
的同义词,但它是类型的同义词 long int
。
答案 1 :(得分:3)
AFAIK,一旦 long
有效,就没有语法规则告诉T
T
是有效类型类型。 (但限定符有一些相关规则,例如volatile
或const
)
换句话说,long long
应该几乎被视为“多字关键字”(但C& C ++标准化委员会非常不愿意引入新的关键字)。
因此,我认为以下内容无效
// probably invalid
typedef int fooT;
unsigned fooT barv;
答案 2 :(得分:1)
[dcl.type] 的第2段规定了long
,short
,signed
,unsigned
,{{1}的规则}和const
。
作为一般规则,在声明的完整decl-speci-seq或类型-peci-seq或trailing-type-speci-seq中,最多只允许一个类型指定者。此规则的唯一例外如下:
const可以与除自身之外的任何类型指定器组合使用。
volatile可以与除自身之外的任何类型指定者组合使用。
signed或unsigned可以与char,long,short或int结合使用。
短或长可与int结合使用。
长可以加倍。
long可与long结合使用。
因此
volatile
是有效的,因为{/ 1}}可以与任何类型说明符组合在一起
typedef long i1;
typedef const i1 i2;
不是因为const
是typedef long i1;
typedef long i1 i2;
的名称,但它本身并不是说明符i1
。
long
在语法上可能与关键字等效,但它不在允许的说明符中与long
组合。它是一个不同的关键字,因此与i1
组合的规则不适用于它。
答案 3 :(得分:0)
注意引入同义词概念的目的可能会有所帮助。 C 中添加了同义词以解决定义结构时的自动引用问题。 例如,在定义用于表示链表中元素的结构类型时,您可能希望如下定义:
typedef struct {
int some_data; ///< ...or anything
linked_list_element_t* previous_element;
linked_list_element_t* next_element;
} linked_list_element_t;
问题当然是类型“linked_list_element_t”仅在typedef struct语句之后定义,因此不能在typedef struct语句中使用。 您当然可以使用通用的 void* 指针,但这不是一个好的做法,并且可以将 previous_element 和 next_element 成员初始化为指向任何东西。
您需要从类型定义中引用类型。输入同义词:
typedef struct lle_t {
int some_data;
lle_t* previous_element;
lle_t* next_element;
} linked_list_element_t;
在这个简单的例子中,代码将只使用linked_list_element_t 来引用类型。