为什么 GCC 定义一元运算符 '&&' 而不是只使用 '&'?
Why does GCC define unary operator '&&' instead of just using '&'?
如 this question 中所述,GCC 定义了非标准的一元运算符 &&
来获取标签的地址。
为什么它定义了一个新的运算符,而不是使用 &
运算符的现有语义,and/or 函数的语义(其中 foo
和 &foo
两者都产生函数的地址 foo()
)?
标签名称不会干扰其他标识符,因为它们仅在 goto 中使用。变量和标签可以具有相同的名称,并且在标准 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
GCC 添加了此 extension 以用于初始化将用作跳转的静态数组 table:
static void *array[] = { &&foo, &&bar, &&hack };
其中 foo
、bar
和 hack
是标签。然后可以通过索引选择一个标签,像这样:
goto *array[i];
标准说
C11:6.2.1 标识符的范围 (p1):
An identifier can denote an object; a function; a tag or a member of a structure, union, or enumeration; a typedef name; a label name; a macro name; or a macro parameter.
第 6.2.3 节进一步说明:
If more than one declaration of a particular identifier is visible at any point in a translation unit, the syntactic context disambiguates uses that refer to different entities. Thus, there are separate name spaces for various categories of identifiers, as follows:
— label names (disambiguated by the syntax of the label declaration and use);
— the tags of structures, unions, and enumerations (disambiguated by following any32) of the keywords struct
, union
, or enum
);
— the members of structures or unions; each structure or union has a separate name space for its members (disambiguated by the type of the expression used to access the member via the .
or ->
operator);
— all other identifiers, called ordinary identifiers (declared in ordinary declarators or as enumeration constants).
这意味着一个对象和一个标签可以用相同的标识符表示。此时,为了让编译器知道foo
的地址是一个标签的地址,而不是一个对象foo
(如果存在)的地址,GCC定义了&&
操作符标签地址。
如 this question 中所述,GCC 定义了非标准的一元运算符 &&
来获取标签的地址。
为什么它定义了一个新的运算符,而不是使用 &
运算符的现有语义,and/or 函数的语义(其中 foo
和 &foo
两者都产生函数的地址 foo()
)?
标签名称不会干扰其他标识符,因为它们仅在 goto 中使用。变量和标签可以具有相同的名称,并且在标准 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
GCC 添加了此 extension 以用于初始化将用作跳转的静态数组 table:
static void *array[] = { &&foo, &&bar, &&hack };
其中 foo
、bar
和 hack
是标签。然后可以通过索引选择一个标签,像这样:
goto *array[i];
标准说
C11:6.2.1 标识符的范围 (p1):
An identifier can denote an object; a function; a tag or a member of a structure, union, or enumeration; a typedef name; a label name; a macro name; or a macro parameter.
第 6.2.3 节进一步说明:
If more than one declaration of a particular identifier is visible at any point in a translation unit, the syntactic context disambiguates uses that refer to different entities. Thus, there are separate name spaces for various categories of identifiers, as follows:
— label names (disambiguated by the syntax of the label declaration and use);
— the tags of structures, unions, and enumerations (disambiguated by following any32) of the keywords
struct
,union
, orenum
);— the members of structures or unions; each structure or union has a separate name space for its members (disambiguated by the type of the expression used to access the member via the
.
or->
operator);— all other identifiers, called ordinary identifiers (declared in ordinary declarators or as enumeration constants).
这意味着一个对象和一个标签可以用相同的标识符表示。此时,为了让编译器知道foo
的地址是一个标签的地址,而不是一个对象foo
(如果存在)的地址,GCC定义了&&
操作符标签地址。