extern int a;
int a = 1;
int main(void)
{
return 0;
}
这是UB吗?标准在 6.2.2/7 中说
如果在翻译单元内,相同的标识符同时出现在内部和外部链接中,则行为未定义。
默认链接是 extern
. 说明extern
符表明它可能在另一个翻译单元或同一个翻译单元中定义和初始化。声明的相对位置extern
无关紧要,否则它们会有些危险。
C99 TC2 §6.9.2/1
如果对象标识符的声明具有文件范围和初始化程序,则该声明是标识符的外部定义。
接下来是一个例子:
int i1 = 1; // definition, external linkage
…
extern int i1; // refers to previous, whose linkage is external
这是完全定义的行为。这就是编译器在包含头文件后的预处理后得到的结果。
你的困惑似乎来自:
int a = 1;
没有内部联系。在文件范围内a
具有外部链接。如果添加了说明符,它将具有内部链接static
。
答案是肯定的和否定的。
如果a
在同一翻译单元的其他地方定义,那么是的,这是未定义的行为。
如果a
未在其他任何地方定义,则int a=1
;将被视为(尽管在同一文件中定义)的外部定义。a
所以它不是未定义的。
是的,我认为这将导致(依赖于工具链的)行为。为什么?
编译器在翻译诸如int a = ...;
. 该行extern int a;
告诉编译器对“a”的每个引用都将由链接器解析。
这留下了编译器处理这种矛盾的两种可能方式: 1. 偶然(因为您只有一个名为“a”的可见符号)链接器将引用绑定到同一翻译单元的已创建符号“a”。2.编译器忽略extern语句,直接绑定到本编译单元的a。
必须将“内部”符号声明为静态(static int a = ...;
),然后我认为你会得到你的 UB。