【发布时间】:2020-11-15 15:11:24
【问题描述】:
每个 Google 搜索都将它们解释为“变量的名称”,但我感觉标识符和标识符的名称之间存在区别。标识符是否更像具有名称、范围、链接和基础对象等属性的对象?我问这个是因为我在尝试通读 C 标准时遇到了一些麻烦。例如,sn-p
int main(){
int x;
extern int x;
}
编译失败而
int main(){
int x;
if(1){extern int x;}
}
编译成功。在this 问题中,第一个sn-p 的失败是从C 标准中的6.2.2.6 开始解释的,其中指出局部变量没有链接。但是,在第二个 sn-p 中,局部变量仍然没有链接,但没有冲突。现在,6.2.2.4 州
对于使用存储类说明符 extern 在该标识符的先前声明可见的范围内声明的标识符,如果先前声明指定内部或外部链接, 后面声明的标识符链接与前面指定的链接相同 宣言。如果前面的声明不可见,或者前面的声明没有指定链接,则 标识符有外部链接。
我的解释是该规则在两个 sn-ps 中都有效,但在第一个规则中,x 的底层对象的唯一性通过 6.2.1.2 触发了约束违规,因为相同的标识符名称是用于具有相同范围和名称空间的两个不同对象。但这不是我之前链接的问题的答案中给出的解释。在第二个 sn-p 中,链接类型仍然存在冲突,那么更改 extern 声明的范围是否会改变本地声明的可见性?从 C 标准的抽象角度考虑链接的最佳方式是什么(不使用 gcc 或 clang 等实际实现作为说明)?
【问题讨论】:
-
6.2.2.6 只是说没有
extern存储类说明符的本地标识符没有链接。 -
链接是指范围内的名称。第二个示例编译,因为
if块范围内的名称x与封闭main主体中的x不同。例如,请参阅this snippet。 -
@dxiv 我试图弄清楚为什么 if 块中的声明根据 C 标准引用了不同的实体。为什么这个实体与在
main之外声明为static int x;的实体不同? -
@GuachoPerez 与
if(1) {int x;}掩盖外部x的原因相同。如果您在文件级别添加static int x;,由于链接冲突,这将再次成为错误。 -
@dxiv 但在第二个 sn-p 中将
static int x;添加到main之外可以正常编译。编译器如何知道extern int x与int x不同但与static int x不同?
标签: c compilation linkage