Gua*_*rez 0 c compilation linkage
每个 Google 搜索都将它们解释为“变量的名称”,但我感觉标识符和标识符的名称之间存在区别。标识符是否更像是具有名称、范围、链接和底层对象等属性的对象?我问这个是因为我在尝试阅读 C 标准时遇到了一些麻烦。例如,片段
int main(){
int x;
extern int x;
}
Run Code Online (Sandbox Code Playgroud)
编译失败而
int main(){
int x;
if(1){extern int x;}
}
Run Code Online (Sandbox Code Playgroud)
编译成功。在这个问题中,第一个片段的失败是从 C 标准中的 6.2.2.6 解释的,它指出局部变量没有链接。然而,在第二个片段中,局部变量仍然没有链接,但没有冲突。现在,6.2.2.4 状态
对于在该标识符的先前声明可见的范围内使用存储类说明符 extern 声明的标识符,如果先前声明指定内部或外部链接,则后面声明中标识符的链接与链接相同在事先声明中指定。如果没有可见的先前声明,或者如果先前声明没有指定链接,则标识符具有外部链接。
我的解释是这个规则在两个片段中都有效,但在第一个片段中,底层对象的唯一性x通过 6.2.1.2 触发了约束违规,因为相同的标识符名称用于两个不同的对象,相同的范围和名称空间。但这不是我之前链接的问题的答案中给出的解释。在第二个片段中,链接类型仍然存在冲突,那么更改extern声明的范围是否会更改本地声明的可见性?从 C 标准的抽象角度考虑链接的最佳方法是什么(不使用 gcc 或 clang 等实际实现作为说明)?
“标识符”是语言语法的一个元素。预处理后,所有标记都是以下之一:keyword、identifier、constant、string-literal或punctuator。
如果标记以字母(或下划线)开头,则它只能是关键字或标识符。如果它不在关键字表中,那么它就是一个标识符。有关这方面的更多技术细节,请参阅 C 标准的附录 A。
在你的程序x和main是标识符,int,if和extern是关键字,1是一个常数,和其他一切是一个标点符号。
标识符用作实体的名称。可以在不同的范围内使用相同的标识符来指定不同的实体(或相同的实体)。链接是标识符与实体相关联的过程的名称。
有时标准使用“标识符”一词来表示由标识符标识的实体,这在 6.2.1/5 中有所涉及:
除非另有明确说明,否则本国际标准使用术语“标识符”来指代某个实体(与句法结构相反),它指的是相关名称空间中的实体,其声明在标识符出现的点是可见的。
由于 6.7/3,第一个代码是错误的:
如果标识符没有链接,则标识符的声明(在声明符或类型说明符中)不应超过一个具有相同作用域和相同名称空间的声明,除了: [...]
在int x;没有联动所以不得的另一个定义x在同一范围内。(例外列表没有任何与此案例相关的内容)。
在第二个代码中,没有违反 6.7/3,因为第二个声明与第一个声明不在同一范围内。您引用的文本解释了extern int x;名称与实体不同的名称int x;,这很好。
由于声明了具有外部链接的标识符但未提供定义,因此第二个程序具有未定义的行为(不需要诊断)。您可能会也可能不会看到错误消息。