Why use the extern keyword in header in C?
为什么要在以下代码中使用extern关键字:
标题
1
| float kFloat; // some say I should write 'extern float kFloat;', but why? |
C文件
1 2 3 4
| #include <stdio.h>
#include"Header.h"
float kFloat = 11.0f; |
主C
1 2 3 4 5 6 7 8 9 10
| #include <stdio.h>
#include"Header.h"
int main (int argc , const char * argv [])
{
printf("The global var is %.1f
", kFloat );
return 0;
} |
此代码有效。全局变量kfloat默认为外部链接和静态生存期。
输出为:
The global var is 11.0
我不明白在哪种情况下会发生问题,有人能给我举个例子,它会在哪里崩溃吗?
声明kFloat而不定义它。
但是:
同时声明了kFloat,但是kFloat的暂定定义。
添加extern只会抑制暂定定义。在头文件中,您只需要声明,而不需要定义。
如果临时定义包含在多个源文件中,那么您将最终拥有同一对象的多个定义,这在C中是未定义的行为。
- 啊,我读了C语言中的特殊的暂定定义规则,谢谢你提出。下面是一个描述良好的链接:stackoverflow.com/questions/3095861/about temporative definiti&zwnj;&8203;on
我为什么要用外部的?
嗯,你不应该。简单明了。因为不应该使用全局变量,它们是唯一需要extern关键字的变量。
每当你想使用一个全局变量时,再想想。在绝对最大值时,您可能需要使用一个具有文件作用域的变量(使用static关键字),通常这样的变量会伴随一些操作/使用其值的函数,但变量本身不应在文件作用域之外可见。使用全局变量只会导致难以处理的混乱代码,如果不引入大量错误,几乎不可能更改这些代码。
- 有些书建议使用全局常量变量而不是宏,因为添加了类型信息。
- 啊,是的,这将是extern关键字的一个有效使用,因为这样的"变量"不是变量而是常量。然而,由于C不能消除像C++那样的变量的运行时存储,所以其他的书阻碍使用EDCOX1 2变量。如果我不使用#define,我可以使用enum或static const变量作为编译时间常数,而不是extern。
- 在你的断言背后有一个真理的元素,但也有一个过度陈述的元素。例如,全局变量stdin、stdout和stderr比不使用全局变量的方案方便得多。我想,您可以创建函数来"获取"值,但它不会是同一个世界。
首先,奇怪的是您的代码正在编译。对于File.c中的kFloat变量的双重定义,应该抛出编译时错误。
其次,如果您试图在两个文件中使用公共变量,那么它不应该在header.h中定义。您应该在头文件中使用extern关键字,以便包含header.h的文件知道它是在外部定义的。
现在,您可以在任何C文件中全局定义变量,然后将该变量用作公共变量。
- 但是头中的定义有默认的外部链接,所以我不需要extern关键字来访问变量。我使用C11编译器,甚至用C99进行了尝试,都没有警告。
- @Viktorlexington:头文件中的定义是暂定的,因为它没有在那里初始化。因此,它不会抛出任何错误,因为它不会与任何实际定义冲突。当kfloat在file.c中初始化时,它得到了真正的定义。所以相同的变量在main.c和file.c中都是可见的,具有相同的值。现在,特别是在这种情况下,在初始化头文件中的变量之前,不需要外部变量。但我建议在头文件中使用extern,因为如果在任何一个C文件中都没有提供定义,则会出现错误。
- 有关更多信息,请参阅以下文章中的答案:stackoverflow.com/questions/8108634/&hellip;
始终将全局变量的定义(如float kFloat;放在.c文件中,并将声明(如extern float kFloat;放在头中)。
否则,当多个.c文件包含相同的头文件时,将出现多个定义错误。
- 我无法重现定义错误,我真的不明白你的意思。
- @viktorlexington链接时发生错误,而不是编译,您进行链接了吗?
- 我运行main.c代码和输出打印没有问题,所以它们都是链接的。输出值为11.0。
- @我明白了。所以在你的主.c中,你还有float kFloat = 11.0f;,这是初步的定义,看@ouah的回答,他对此有更好的解释。要重现多个定义错误,需要删除此错误,并且只在头中包含定义。
- 但关键是:我没有错误,为什么要更改代码。当然,如果我在代码中更改了错误的东西,我会得到错误,但是当我在一个更大的项目中使用这个代码时,错误在哪里呢?
- @Viktorlexington如果我理解正确的话,暂定的定义仍然是定义,所以如果头包含在多个文件中,那么您将有未定义的行为。未定义的行为意味着即使在一台机器上一切正常,在另一台机器上也可能不正常。
extern表示在您想要使用的项目(或外部功能块)中的某个地方定义了一个变量。它不为它分配内存,因为您告诉编译器这是在别处定义的。
变量必须在程序的某个模块中定义一次。如果没有定义或定义不止一个,则可能会在链接阶段产生错误。
定义是指变量被创建或分配存储的位置;声明是指变量的性质被指定但没有分配存储的位置。
因为它可以在其他地方访问,所以需要是静态的。
- 但是我的变量被定义了。两者都是外部链接和静态生存期。你的意思是什么?