关于外部的混淆与C中的函数定义

时间:2013-02-03 11:47:48

标签: c

  

可能重复:
  Effects of the `extern` keyword on C functions

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

编译时由编译器生成的警告(我使用gcc 4.2.1):

extern int var = 10;

支持这一点。使用extern时,这应该只是一个声明,因此它不正确。

然而,让我感到困惑的是输入此内容时没有警告或其他任何内容:

extern int func() {return 5;}

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

如果有人向我解释,我将非常感激。谢谢!

2 个答案:

答案 0 :(得分:5)

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

extern void foo(int bar);

相当于

void foo(int bar);

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

  1. 仅提供声明(即原型)或
  2. 提供一个定义,在没有原型的情况下也可以作为声明。
  3. 但是,对于变量,您有三个选项:

    1. 仅提供声明,
    2. 使用默认初始值设定项提供定义:int var;不包含= 10部分,或
    3. 提供具有特定初始值设定项的定义:int var = 10
    4. 由于函数只有两个选项,因此编译器可以在不使用extern关键字的情况下进行区分。默认情况下,任何没有static个关键字的声明都会被视为extern。因此,extern关键字将被所有函数声明或定义忽略。

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

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

答案 1 :(得分:3)

  

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

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

void foo();

是一个函数声明,但是

int i;

是变量定义。

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