C 中的标识符到底是什么?
What are identifiers in C exactly?
每次 Google 搜索都将它们解释为“变量的名称”,但我感觉标识符和标识符的名称之间存在区别。标识符是否更像是具有名称、范围、链接和底层对象等属性的对象?我问这个是因为我 运行 在尝试通读 C 标准时遇到了一些麻烦。例如,片段
int main(){
int x;
extern int x;
}
编译失败而
int main(){
int x;
if(1){extern int x;}
}
编译成功。在 问题中,第一个片段的失败是从 C 标准中的 6.2.2.6 中解释的,其中指出局部变量没有链接。然而,在第二个片段中,局部变量仍然没有链接,但也不存在冲突。现在,6.2.2.4 状态
For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible, if the prior declaration specifies internal or external linkage,
the linkage of the identifier at the later declaration is the same as the linkage specified at the prior
declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the
identifier has external linkage.
我的解释是这条规则在两个片段中都有效,但在第一个片段中,x
的基础对象的唯一性通过 6.2.1.2 触发了约束冲突,因为相同的标识符name 被用于具有相同作用域和名称 space 的两个不同对象。但这不是我之前链接的问题的答案中给出的解释。在第二个片段中,链接类型仍然存在冲突,那么更改 extern
声明的范围是否会改变局部声明的可见性?从 C 标准的抽象角度考虑链接的最佳方式是什么(不使用 gcc 或 clang 等实际实现作为说明)?
“标识符”是语言语法的一个元素。预处理后,所有的token都是以下之一:keyword, identifier, constant, 字符串文字或标点符号.
如果令牌以字母(或下划线)开头,则它只能是关键字或标识符。如果它不在关键字的 table 中,那么它就是一个标识符。有关这方面的更多技术细节,请参阅 C 标准的附件 A。
在你的程序中x
和main
是标识符,int
,if
和extern
是关键字,1
是常量, 其他都是标点符号。
标识符用作实体的名称。在不同的范围内可以使用相同的标识符来指定不同的实体(或同一实体)。 链接 是标识符与实体相关联的过程的名称。
有时标准使用“标识符”一词来表示由标识符标识的实体,这在 6.2.1/5 中有所介绍:
Unless explicitly stated otherwise, where this International Standard uses the term “identifier” to refer to some entity (as opposed to the syntactic construct), it refers to the entity in the relevant name space whose declaration is visible at the point the identifier occurs.
由于 6.7/3,第一个代码是错误的:
If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or type specifier) with the same scope and in the same name space, except that: [...]
int x;
没有链接,因此在同一范围内不应有另一个 x
的定义。 (例外列表与此案例没有任何关系)。
在第二个代码中,没有违反 6.7/3,因为第二个声明与第一个声明不在同一范围内。您引用的文字解释说 extern int x;
命名的实体与 int x;
命名的实体不同,这很好。
第二个程序具有未定义的行为(不需要诊断),因为声明了具有外部链接的标识符但未提供定义。您可能会看到也可能不会看到错误消息。
每次 Google 搜索都将它们解释为“变量的名称”,但我感觉标识符和标识符的名称之间存在区别。标识符是否更像是具有名称、范围、链接和底层对象等属性的对象?我问这个是因为我 运行 在尝试通读 C 标准时遇到了一些麻烦。例如,片段
int main(){
int x;
extern int x;
}
编译失败而
int main(){
int x;
if(1){extern int x;}
}
编译成功。在
For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible, if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.
我的解释是这条规则在两个片段中都有效,但在第一个片段中,x
的基础对象的唯一性通过 6.2.1.2 触发了约束冲突,因为相同的标识符name 被用于具有相同作用域和名称 space 的两个不同对象。但这不是我之前链接的问题的答案中给出的解释。在第二个片段中,链接类型仍然存在冲突,那么更改 extern
声明的范围是否会改变局部声明的可见性?从 C 标准的抽象角度考虑链接的最佳方式是什么(不使用 gcc 或 clang 等实际实现作为说明)?
“标识符”是语言语法的一个元素。预处理后,所有的token都是以下之一:keyword, identifier, constant, 字符串文字或标点符号.
如果令牌以字母(或下划线)开头,则它只能是关键字或标识符。如果它不在关键字的 table 中,那么它就是一个标识符。有关这方面的更多技术细节,请参阅 C 标准的附件 A。
在你的程序中x
和main
是标识符,int
,if
和extern
是关键字,1
是常量, 其他都是标点符号。
标识符用作实体的名称。在不同的范围内可以使用相同的标识符来指定不同的实体(或同一实体)。 链接 是标识符与实体相关联的过程的名称。
有时标准使用“标识符”一词来表示由标识符标识的实体,这在 6.2.1/5 中有所介绍:
Unless explicitly stated otherwise, where this International Standard uses the term “identifier” to refer to some entity (as opposed to the syntactic construct), it refers to the entity in the relevant name space whose declaration is visible at the point the identifier occurs.
由于 6.7/3,第一个代码是错误的:
If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or type specifier) with the same scope and in the same name space, except that: [...]
int x;
没有链接,因此在同一范围内不应有另一个 x
的定义。 (例外列表与此案例没有任何关系)。
在第二个代码中,没有违反 6.7/3,因为第二个声明与第一个声明不在同一范围内。您引用的文字解释说 extern int x;
命名的实体与 int x;
命名的实体不同,这很好。
第二个程序具有未定义的行为(不需要诊断),因为声明了具有外部链接的标识符但未提供定义。您可能会看到也可能不会看到错误消息。