2013-02-03 29 views
9

可能重复:
Effects of the `extern` keyword on C functions混乱关于与函数定义的extern用C

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

而且打字时由编译器(我用gcc 4.2.1)所产生的警告:

extern int var = 10; 

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

然而,这是混淆了我的事情是打字时没有警告或任何东西:

extern int func() {return 5;} 

这是一个定义,它应该产生同样的警告,但事实并非如此。对此的唯一解释是在此处找到的是该定义覆盖了extern关键字。但是,遵循这个逻辑,为什么它在变量定义时不会覆盖它?或者,当与变量一起使用时,关键字是否有特殊含义?

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

+3

最后一个分号正在扰乱我。 –

+1

看看[这个链接]是否有帮助(http://stackoverflow.com/questions/856636/effects-of-the-extern-keyword-on-c-functions)有帮助。 –

+1

问题必须是变量的初始化 – nabroyan

回答

5

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

extern void foo(int bar); 

相当于

void foo(int bar); 

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

  1. 只提供一个声明(即原型)或
  2. 提供一个定义,该定义也可用作缺少原型的声明。

有了变数,但是,你有三种选择:

  1. 只提供一个声明,
  2. 提供的默认初始值的定义:没有= 10部分int var;,或
  3. 提供一个使用特定的初始化程序定义:int var = 10

Sin ce只有两个功能选项,编译器可以区分那么不用使用extern关键字。任何没有static关键字的声明默认为extern。因此,extern关键字在所有函数声明或定义中都将被忽略。

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

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

+0

有关对象(而非变量)声明的声明不正确。在文件范围内:'int x;'是具有外部链接的对象的临时定义,'extern int x;'是具有外部链接的对象声明,int x = 3;'extern int x = 3 ;'都是具有外部链接的对象的定义。在块范围内:'int x;'是没有链接的对象的定义,'extern int x;'是具有外部链接的对象声明,int x = 3;'是一个没有链接的对象的定义链接和'extern int x = 3;'是不允许的,由C 2011 6.7.9 5. ... –

+0

以上假设每个声明是标识符第一次出现在该范围内。否则,会有复杂性。例如,'static int x; extern int x;'是允许的,后者'x'与前者'x'相同。另外,尽管一些编译器在文件范围内发出了'extern int x = 3;'的警告,但在C 2011的示例中它明确显示为有效6.9.2 4. –

+0

@EricPostpischil我编辑了答案,感谢评论。 – dasblinkenlight

3

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

变量和函数之间的差别在于

void foo(); 

是一个函数声明,

int i; 

是可变定义。

如果在多个文件中有变量定义,那么编译器会多次为该变量生成存储(并且很可能会出现链接器错误)。功能并非如此。

+1

我认为当我们有'extern int x = 1;'这看起来像一个声明和一个具有初始化器的定义时,这是最令人困惑的。 –

+0

在文件范围内,'int i;'是一个暂时的定义,而不是一个定义,它既不会产生多次存储也不会导致链接错误。 –