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

关于C中函数定义与外部的混淆,c,C,可能重复: 好的,几个小时以来我读了很多关于extern关键字的意思。还有最后一件事一直困扰着我,我找不到任何信息。 据我所知,extern关键字基本上告诉编译器变量或函数只是一个声明,它是在某个地方定义的,因此它不必担心这一点,链接器将处理它 以及编译器(我使用gcc 4.2.1)在键入以下内容时生成的警告: extern int var = 10; extern int func() {return 5;} 支持这一点。对于extern这应该是一个声明,因此它是不正确的 然而,让我困惑

可能重复:

好的,几个小时以来我读了很多关于extern关键字的意思。还有最后一件事一直困扰着我,我找不到任何信息。 据我所知,
extern
关键字基本上告诉编译器变量或函数只是一个声明,它是在某个地方定义的,因此它不必担心这一点,链接器将处理它

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

extern int var = 10;
extern int func() {return 5;}
支持这一点。对于
extern
这应该是一个声明,因此它是不正确的

然而,让我困惑的是,键入以下内容时没有警告或任何内容:

extern int var = 10;
extern int func() {return 5;}
这是一个定义,它应该生成相同的警告,但它没有。我在这里能找到的唯一解释是定义覆盖了
extern
关键字。然而,遵循这个逻辑,当它是一个变量定义时,为什么不重写它呢?或者,当与变量一起使用时,关键字是否具有特殊意义

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

然而,遵循这个逻辑,当它是一个变量定义时,为什么不重写它呢?或者,当与变量一起使用时,关键字是否具有特殊意义

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

void foo();
是一个函数声明,但是

int i;
是一个变量定义。


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

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

extern void foo(int bar);
相当于

void foo(int bar);
声明/定义函数时,有两个选项:

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

  • 只提供一份声明
  • 使用默认初始值设定项提供定义:
    int-var不带
    =10
    部分,或
  • 提供具有特定初始值设定项的定义:
    int var=10
  • 由于函数只有两个选项,编译器可以在不使用
    extern
    关键字的情况下区分它们。默认情况下,没有
    静态
    关键字的任何声明都被视为
    外部
    。因此,所有函数声明或定义都会忽略
    extern
    关键字

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


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

    最后一个分号让我感到困扰。请查看是否有帮助。问题必须是变量的初始化。虽然此问题名义上是重复的,但建议的原始答案质量较低。它过于冗长、不清楚、不完全准确,并且提供了不相关的误导性建议看起来既像一个声明,又像一个带有初始值设定项的定义
    是一个暂定定义,不是定义,它既不会多次生成存储,也不会导致链接错误。有关对象(非变量)声明的语句不正确。在文件范围:
    intx
    是具有外部链接的对象的暂定定义,
    extern intx
    是具有外部链接的对象的声明,
    intx=3
    extern int x=3都是具有外部链接的对象的定义。在块范围内:
    intx
    是一个没有链接的对象定义,
    extern int x
    是具有外部链接的对象的声明,
    intx=3
    是没有链接的对象的定义,并且
    extern int x=3是不允许的……以上假定每个声明都是标识符第一次出现在该范围内。否则,就会出现并发症。例如,
    static int x;外部INTX,后者
    x
    与前者
    x
    相同。此外,尽管有些编译器发出警告,提示
    extern int x=3
    在文件范围内,它在C 2011 6.9.2 4的示例中显式显示为有效。@EricPostSchil我编辑了答案,感谢您的评论。