0
extern int a;
int a = 1;

int main(void)
{
  return 0;
}

这是UB吗?标准在 6.2.2/7 中说

如果在翻译单元内,相同的标识符同时出现在内部和外部链接中,则行为未定义。

4

4 回答 4

5

默认链接 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
于 2013-01-24T11:07:02.740 回答
5

这是完全定义的行为。这就是编译器在包含头文件后的预处理后得到的结果。

你的困惑似乎来自:

int a = 1;

没有内部联系。在文件范围内a具有外部链接。如果添加了说明符,它将具有内部链接static

于 2013-01-24T11:16:55.773 回答
1

答案是肯定的和否定的。

如果a在同一翻译单元的其他地方定义,那么是的,这是未定义的行为。

如果a未在其他任何地方定义,则int a=1;将被视为(尽管在同一文件中定义)的外部定义。a所以它不是未定义的。

于 2013-01-24T11:16:48.930 回答
-2

是的,我认为这将导致(依赖于工具链的)行为。为什么?

编译器在翻译诸如int a = ...;. 该行extern int a;告诉编译器对“a”的每个引用都将由链接器解析。

这留下了编译器处理这种矛盾的两种可能方式: 1. 偶然(因为您只有一个名为“a”的可见符号)链接器将引用绑定到同一翻译单元的已创建符号“a”。2.编译器忽略extern语句,直接绑定到本编译单元的a。

必须将“内部”符号声明为静态(static int a = ...;),然后我认为你会得到你的 UB。

于 2013-01-24T11:09:18.147 回答