在翻译单位中使用extern

时间:2013-01-24 10:58:31

标签: c extern linkage

extern int a;
int a = 1;

int main(void)
{
  return 0;
}

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

如果在翻译单元内,同一标识符同时显示内部和外部 联系,行为未定义。

4 个答案:

答案 0 :(得分:5)

默认链接 externextern说明符表示它可能在另一个翻译单元或同一个翻译单元中定义和初始化。 extern声明的相对位置无关紧要,或者它们会有些危险。

C99TC2§6.9.2/ 1

  

如果对象的标识符声明具有文件范围和初始值设定项,则声明是标识符的外部定义。

接下来是一个例子:

int i1 = 1;  // definition, external linkage
…
extern int i1;  // refers to previous, whose linkage is external

答案 1 :(得分:5)

这是完美定义的行为。这是编译器在包含标头后进行预处理后会得到的结果。

你的困惑似乎来了:

int a = 1;

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

答案 2 :(得分:1)

答案是肯定的,不是。

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

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

答案 3 :(得分:-2)

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

编译器在翻译int a = ...;之类的代码时生成(对于链接器)可见符号“a”。行extern int a;告诉编译器,每个对'a'的引用都将由链接器解析。

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

'内部'符号必须声明为静态(static int a = ...;),然后你才能得到你的UB。