1

a) 外部变量的定义与局部变量的定义相同,即int i=2;(仅在所有函数之外)。但为什么extern int i=2;定义太有效了?不是extern只用在其他文件的变量声明中吗?

b) 文件 1

  #include<stdio.h>
  int i=3;
  int main()
  {
      printf("%d",i);
      fn();
  }

文件2

  int i;  //  although the declaration should be: extern int i; So, why is this working?
  void fn()
  {
      printf("%d",i);
  }

输出:两种情况下均为 3

4

2 回答 2

5

由于历史原因,确定链接以及声明何时提供定义的规则有点混乱。

对于您的特定示例,在文件范围内

extern int i = 2;

int i = 2;

是等效的外部定义,即extern如果您提供初始化程序,则它是可选的。

但是,如果您不提供初始化程序,extern不是可选的:

int i;

是一个带有外部链接的暂定定义,它变成一个外部定义等价于

int i = 0;

如果翻译单元不包含具有显式初始化程序的另一个定义。

这不同于

extern int i;

这从来都不是一个定义。如果已经有另一个可见的相同标识符的声明,那么变量将从那里获得它的链接;如果这是第一个声明,则变量将具有外部链接。

这意味着在您的第二个示例中, file1 和 file2 都提供了 的外部定义i,这是未定义的行为,并且链接器可以自由选择它最喜欢的定义(它也可能试图让恶魔飞出你的鼻子)。C 有一个共同的扩展(参见 C99 附件 J.5.11 和这个问题),这使得这个特殊情况得到了很好的定义。

于 2012-05-04T17:20:52.223 回答
1

在 C 中,extern带有初始化的 an 会导致分配一个变量。也就是说,该声明将被视为定义声明。这与更常见的extern.

C标准说:

6.9.2 外部对象定义

......

如果对象标识符的声明具有文件范围和初始化程序,则该声明是标识符的外部定义。

至于您问题的第二部分,您int i在文件范围内的声明具有外部链接。如果你想给它内部链接,你需要声明它static int i。C标准说:

6.2.2 标识符的链接

……

如果对象标识符的声明具有文件范围且没有存储类说明符,则其链接是外部的。

于 2012-05-04T16:29:12.447 回答