9

可能重复:
`extern` 关键字对 C 函数的影响

好的,所以几个小时以来,我已经阅读了很多关于 extern 关键字含义的内容。还有最后一件事让我无法找到任何信息。据我了解,extern关键字基本上告诉编译器变量或函数只是一个声明,并且它是在某个地方定义的,所以它不必担心,链接器会处理它。

并且在键入以下内容时编译器生成的警告(我使用的是 gcc 4.2.1):

extern int var = 10;

支持这一点。这extern应该只是一个声明,所以它是不正确的。

但是,让我感到困惑的是在输入以下内容时没有警告或任何内容:

extern int func() {return 5;}

这是一个定义,它应该生成相同的警告,但它不会。我能在这里找到的唯一解释是定义覆盖了extern关键字。但是,遵循该逻辑,为什么当它是变量定义时它不覆盖它?或者关键字与变量一起使用时是否具有特殊含义?

如果有人向我解释这一点,我将不胜感激。谢谢!

4

2 回答 2

5

关键字确实只有在与变量一起使用extern时才具有特殊含义。使用extern函数原型是完全可选的:

extern void foo(int bar);

相当于

void foo(int bar);

当你声明/定义一个函数时,你有两个选择:

  1. 仅提供声明(即原型),或
  2. 提供一个定义,在没有原型的情况下也可以作为声明。

但是,对于变量,您有三个选择:

  1. 只提供一份声明,
  2. 提供带有默认初始化器的定义:int var;不带= 10部件,或
  3. 提供具有特定初始化程序的定义:int var = 10

extern由于函数只有两个选项,因此编译器可以在不使用关键字的情况下区分 then 。默认情况下会考虑任何没有static关键字的声明。extern因此,extern所有函数声明或定义都会忽略该关键字。

但是,对于变量,需要关键字来区分#1 和#2。当你使用extern时,它是#1;当你不使用时extern,它是#2。当您尝试添加extern到 #3 时,这是一个警告,因为它仍然是一个定义,并且extern被忽略。

所有这些都有些简化:您可以在同一个编译单元中多次提供声明,并且可以在全局范围或块范围内提供它们。有关完整的详细信息,请查看 C 标准的第 6.7.9 5 节。

于 2013-02-03T12:00:28.793 回答
3

但是,遵循该逻辑,为什么当它是变量定义时它不覆盖它?或者关键字与变量一起使用时是否具有特殊含义?

变量和函数的区别在于

void foo();

是一个函数声明,但是

int i;

是一个变量定义。

如果您在多个文件中有变量定义,那么编译器将多次生成该变量的存储(并且很可能您会收到链接器错误)。这不是函数的情况。

于 2013-02-03T11:58:20.810 回答