C中的标识符到底是什么?

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 等实际实现作为说明)?

M.M*_*M.M 5

“标识符”是语言语法的一个元素。预处理后,所有标记都是以下之一:keywordidentifierconstantstring-literalpunctuator

如果标记以字母(或下划线)开头,则它只能是关键字或标识符。如果它不在关键字表中,那么它就是一个标识符。有关这方面的更多技术细节,请参阅 C 标准的附录 A。

在你的程序xmain是标识符,intifextern是关键字,1是一个常数,和其他一切是一个标点符号。


标识符用作实体的名称。可以在不同的范围内使用相同的标识符来指定不同的实体(或相同的实体)。链接是标识符与实体相关联的过程的名称。

有时标准使用“标识符”一词来表示由标识符标识的实体,这在 6.2.1/5 中有所涉及:

除非另有明确说明,否则本国际标准使用术语“标识符”来指代某个实体(与句法结构相反),它指的是相关名称空间中的实体,其声明在标识符出现的点是可见的。


由于 6.7/3,第一个代码是错误的:

如果标识符没有链接,则标识符的声明(在声明符或类型说明符中)不应超过一个具有相同作用域和相同名称空间的声明,除了: [...]

int x;没有联动所以不得的另一个定义x在同一范围内。(例外列表没有任何与此案例相关的内容)。

在第二个代码中,没有违反 6.7/3,因为第二个声明与第一个声明不在同一范围内。您引用的文本解释了extern int x;名称与实体不同的名称int x;,这很好。

由于声明了具有外部链接的标识符但未提供定义,因此第二个程序具有未定义的行为(不需要诊断)。您可能会也可能不会看到错误消息。