我正在定义一个全局变量 test2.h
#ifndef TEST2_H
#define TEST2_H
int test_var;
void use_it(void);
#endif
Run Code Online (Sandbox Code Playgroud)
并在两个不同的文件中再次定义它, test.c
#include <stdio.h>
#include "test2.h"
int test_var;
int main() {
printf("The test_var is: %d\n", ++test_var); // prints 1
use_it(); // prints 2
}
Run Code Online (Sandbox Code Playgroud)
和 test2.c
#include <stdio.h>
#include "test2.h"
int test_var;
void use_it() {
printf("The test_var is: %d", ++test_var);
}
Run Code Online (Sandbox Code Playgroud)
我替换了test_var
with 的定义extern int test_var
并得到了相同的结果.也就是说,在两种情况下都是两个文件,test.c
并且test2.c
可以访问全局变量test_var
.我的印象是,没有extern
,每个文件都有自己的副本test_var
.观察表明情况并非如此.那么什么时候extern
真的做了什么?
你最终得到两个副本,test_var
这是未定义的行为.
(C99,6.9p5)"如果在表达式中使用通过外部链接声明的标识符(除了作为sizeof运算符的操作数的一部分,其结果是整数常量),整个程序中的某个地方应该只有一个外部定义标识符;否则,不得超过一个"
在您的情况下,链接器可能很适合您并合并这两个符号,但这仍然不可移植,并且是未定义的行为.如果您使用的是GNU链接器,则可以使用它--warn-common
来获取警告(--fatal-warnings
如果您想要出错).
要解决您的问题,请将说明extern
符放在文件的声明中test_var
,.h
并删除其中一个定义test_var
(例如test.c
文件中的一个).