extern 关键字真的有必要吗?

发布于 2024-09-01 15:13:29 字数 233 浏览 3 评论 0原文

...
#include "test1.h"

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

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

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

...
#include "test1.h"

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

aaa is defined in test1.h,and I didn't use extern keyword,but still can reference aaa.

So I doubt is extern really necessary?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

孤千羽 2024-09-08 15:13:29

extern 有其用途。但它主要涉及到令人不悦的“全局变量”。 extern 背后的主要思想是通过外部链接来声明事物。因此,它与静态相反。但外部链接在许多情况下是默认链接,因此在这些情况下您不需要 externextern 的另一个用途是:它可以将定义变成声明。例子:

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的含义也被重载了——取决于上下文——控制或不控制链接。它所做的另一件事是控制对象的生命周期(“静态生命周期”)。但在全局范围内,所有变量都已经具有静态生命周期,有些人认为回收用于控制链接的关键字是一个好主意(这只是我的猜测)。

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

extern has its uses. But it mainly involves "global variables" which are frowned upon. The main idea behind extern is to declare things with external linkage. As such it's kind of the opposite of static. But external linkage is in many cases the default linkage so you don't need extern in those cases. Another use of extern is: It can turn definitions into declarations. Examples:

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.

You see, it's rather complicated. There are two orthogonal concepts: Linkage (external vs internal) and the matter of declaration vs definition. The extern keyword can affect both. With respect to linkage it's the opposite of static. But the meaning of static is also overloaded and -- depending on the context -- does or does not control linkage. The other thing it does is to control the life-time of objects ("static life-time"). But at global scope all variables already have a static life-time and some people thought it would be a good idea to recycle the keyword for controlling linkage (this is me just guessing).

Linkage basically is a property of an object or function declared/defined at "namespace scope". If it has internal linkage, it won't be directly accessible by name from other translation units. If it has external linkage, there shall be only one definition across all translation units (with exceptions, see one-definition-rule).

箹锭⒈辈孓 2024-09-08 15:13:29

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

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

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

根据定义,我通常的意思是“分配空间”,例如int等等。

如果您有这样一行:

int aaa;

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

一种更好的方法是在您的一个 C 文件中定义 aaa 变量,然后将:

extern int aaa;

放入您的头文件中。

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

I've found the best way to organise your data is to follow two simple rules:

  • Only declare things in header files.
  • Define things in C (or cpp, but I'll just use C here for simplicity) files.

By declare, I mean notify the compiler that things exist, but don't allocate storage for them. This includes typedef, struct, extern and so on.

By define, I generally mean "allocate space for", like int and so on.

If you have a line like:

int aaa;

in a header file, every compilation unit (basically defined as an input stream to the compiler - the C file along with everything it brings in with #include, recursively) will get its own copy. That's going to cause problems if you link two object files together that have the same symbol defined (except under certain limited circumstances like const).

A better way to do this is to define that aaa variable in one of your C files and then put:

extern int aaa;

in your header file.

Note that if your header file is only included in one C file, this isn't a problem. But, in that case, I probably wouldn't even have a header file. Header files are, in my opinion, only for sharing things between compilation units.

时光匆匆的小流年 2024-09-08 15:13:29

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

在头文件中包含变量和常量的经验法则

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

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

If your test1.h has the definition of aaa and you wanted to include the header file into more than one translation unit you will run into multiple definition error, unless aaa is constant.
Better you define the aaa in a cpp file and add extern definition in header file that could be added to other files as header.

Thumb rule for having variable and constant in header file

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

Since constant have internal linkage in c++ any constant that is defined in a translation unit will not be visible to other translation unit, but it is not the case for variable they have external linkage i.e., they are visible to other translation unit. Putting the definition of a variable in a header, that is shared in other translation unit would lead to multiple definition of a variable, leading to multiple definition error.

前事休说 2024-09-08 15:13:29

在这种情况下,extern 不是必需的。当符号在另一个编译单元中声明时,需要使用 extern。

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

In that case, extern is not necessary. Extern is needed when the symbol is declared in another compilation unit.

When you use the #include preprocessing directive, the included file is copied out in place of the directive. In this case you don't need extern because the compiler already know aaa.

我很OK 2024-09-08 15:13:29

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

If aaa is not defined in another compilation unit you don't need extern, otherwise you do.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文