为什么GCC定义了一元运算符'&&'而不只是使用'&'?

时间:2015-04-28 07:56:09

标签: c gcc unary-operator addressof

正如this question中所讨论的,GCC定义了非标准一元运算符&&来获取标签的地址。

为什么它定义一个新的运算符,而不是使用&运算符的现有语义和/或函数的语义(其中foo&foo都产生地址函数foo())?

2 个答案:

答案 0 :(得分:37)

标签名称不会干扰其他标识符,因为它们仅用于gotos。变量和标签可以具有相同的名称,并且在标准C和C ++中,它始终从上下文中清楚地表达了什么。所以这完全有效:

name:
  int name;
  name = 4; // refers to the variable
  goto name; // refers to the label

&和&&因此需要编译器知道期望的名称类型:

  &name; // refers to the variable
  &&name; // refers to the label

答案 1 :(得分:9)

GCC添加了此extension用于初始化将用作跳转表的静态数组:

static void *array[] = { &&foo, &&bar, &&hack };  

foobarhack是标签。然后可以使用索引选择标签,如下所示:

goto *array[i];   

标准说

C11:6.2.1标识符的范围(p1):

  

标识符可以表示对象;功能;标签或结构,联合或枚举的成员;一个typedef名称; 标签名称;一个宏名;或宏参数。

此外,它在第6.2.3节中说:

  

如果在翻译单元中的任何一点可以看到多个特定标识符的声明,则语法上下文消除了引用不同实体的用法。因此,对于各种类别的标识符,存在单独的名称空间,如下所示

     

- 标签名称 (通过标签声明和使用的语法消除歧义);

     

- 结构,联合和枚举的标记(通过遵循任何 32消除歧义)关键字structunionenum);

     

- 结构或工会的成员;每个结构或联合为其成员都有一个单独的名称空间(通过.->运算符用于访问成员的表达式的类型消除歧义;

     

- 所有其他标识符,称为普通标识符(在普通声明符中声明或作为枚举常量)。

这意味着对象和标签可以用相同的标识符表示。此时,为了让编译器知道foo的地址是标签的地址,而不是对象foo的地址(如果存在),GCC定义了&&运算符标签地址。