外景没有区别

Geo*_*ton 1 c

我正在定义一个全局变量 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_varwith 的定义extern int test_var并得到了相同的结果.也就是说,在两种情况下都是两个文件,test.c并且test2.c可以访问全局变量test_var.我的印象是,没有extern,每个文件都有自己的副本test_var.观察表明情况并非如此.那么什么时候extern真的做了什么?

oua*_*uah 5

你最终得到两个副本,test_var这是未定义的行为.

(C99,6.9p5)"如果在表达式中使用通过外部链接声明的标识符(除了作为sizeof运算符的操作数的一部分,其结果是整数常量),整个程序中的某个地方应该只有一个外部定义标识符;否则,不得超过一个"

在您的情况下,链接器可能很适合您并合并这两个符号,但这仍然不可移植,并且是未定义的行为.如果您使用的是GNU链接器,则可以使用它--warn-common来获取警告(--fatal-warnings如果您想要出错).

要解决您的问题,请将说明extern符放在文件的声明中test_var,.h并删除其中一个定义test_var(例如test.c文件中的一个).