8
...
#include "test1.h"

int main(..)
{
    count << aaa <<endl;
}

aaa中定义的test1.h,我没有使用extern关键字,但仍然可以引用aaa

所以我怀疑extern真的有必要吗?

4

5 回答 5

14

extern有它的用途。但它主要涉及不受欢迎的“全局变量”。背后的主要思想extern是用外部链接声明事物。因此,它与static. 但在许多情况下,外部链接是默认链接,因此在这些情况下您不需要extern。另一个用途extern是:它可以将定义变成声明。例子:

extern int i;  // Declaration of i with external linkage
               // (only tells the compiler about the existence of i)

int i;         // Definition of i with external linkage
               // (actually reserves memory, should not be in a header file)

const int f = 3; // Definition of f with internal linkage (due to const)
                 // (This applies to C++ only, not C. In C f would have
                 // external linkage.) In C++ it's perfectly fine to put
                 // somethibng like this into a header file.

extern const int g; // Declaration of g with external linkage
                    // could be placed into a header file

extern const int g = 3; // Definition of g with external linkage
                        // Not supposed to be in a header file

static int t; // Definition of t with internal linkage.
              // may appear anywhere. Every translation unit that
              // has a line like this has its very own t object.

你看,这相当复杂。有两个正交的概念:链接(外部与内部)以及声明与定义的问题。extern关键字可以影响两者。关于链接,它与static. 但是 的含义static也被重载并且 - 根据上下文 - 控制或不控制链接。它所做的另一件事是控制对象的生命周期(“静态生命周期”)。但是在全局范围内,所有变量都已经有一个静态的生命周期,有些人认为回收控制链接的关键字是个好主意(这只是我的猜测)。

链接基本上是在“命名空间范围”中声明/定义的对象或函数的属性。如果它具有内部链接,则其他翻译单元将无法通过名称直接访问它。如果它具有外部链接,则在所有翻译单元中应该只有一个定义(有例外,请参阅一个定义规则)。

于 2010-05-15T14:11:15.593 回答
7

我发现组织数据的最佳方法是遵循两个简单的规则:

  • 仅在头文件中声明内容。
  • 在 C(或 cpp,但为了简单起见,我在这里只使用 C)文件中定义东西。

通过声明,我的意思是通知编译器事物存在,但不要为它们分配存储空间。这包括typedefstructextern

通过定义,我通常是指“为”分配空间,int等等。

如果你有这样的一行:

int aaa;

在头文件中,每个编译单元(基本上定义为编译器的输入流 - C 文件以及它以#include递归方式引入的所有内容)都将获得自己的副本。如果您将定义了相同符号的两个目标文件链接在一起,那将导致问题(除非在某些有限的情况下,例如const)。

一个更好的方法是在你的一个 C 文件中定义该aaa变量,然后输入:

extern int aaa;

在你的头文件中。

请注意,如果您的头文件只包含在一个 C 文件中,这不是问题。但是,在那种情况下,我什至可能没有头文件。在我看来,头文件仅用于在编译单元之间共享内容。

于 2010-05-15T13:37:32.880 回答
5

如果您的 test1.h 有 aaa 的定义,并且您想将头文件包含到多个翻译单元中,您将遇到多个定义错误,除非 aaa 是常量。最好在 cpp 文件中定义 aaa 并在头文件中添加 extern 定义,该定义可以作为头文件添加到其他文件中。

头文件中变量和常量的拇指规则

 extern int a ;//Data declarations
 const float pi = 3.141593 ;//Constant definitions

由于常量在 C++ 中具有内部链接,因此在翻译单元中定义的任何常量都不会对其他翻译单元可见,但对于具有外部链接的变量来说,情况并非如此,即它们对其他翻译单元可见。将变量的定义放在头文件中,在其他翻译单元中共享会导致变量的多次定义,从而导致多次定义错误。

于 2010-05-15T13:16:40.040 回答
4

在那种情况下,extern是没有必要的。当符号在另一个编译单元中声明时,需要 extern。

当您使用#include预处理指令时,包含的文件将被复制出来以代替指令。在这种情况下,您不需要extern,因为编译器已经知道aaa.

于 2010-05-15T13:17:17.340 回答
2

如果 aaa 未在另一个编译单元中定义,则不需要 extern,否则需要。

于 2010-05-15T13:11:02.063 回答