typedef中同义词的含义

时间:2015-07-07 13:17:12

标签: c++ c++11 standards

以下段落取自[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允许一系列类型说明符,只要它们满足组合规则即可。在我看来,类型与类型说明符不同,即使类型由类型说明符指定; - )

4 个答案:

答案 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 是有效类型类型。 (但限定符有一些相关规则,例如volatileconst

换句话说,long long应该几乎被视为“多字关键字”(但C& C ++标准化委员会非常不愿意引入新的关键字)。

因此,我认为以下内容无效

 // probably invalid
 typedef int fooT;
 unsigned fooT barv;

答案 2 :(得分:1)

[dcl.type] 的第2段规定了longshortsignedunsigned,{{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;

不是因为consttypedef 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 来引用类型。