我正在尝试基于extern的程序,据我所知,这在跨多个只有一个定义的文件中访问变量时很有用。
但是我在没有extern
的情况下尝试了一个简单的程序,当我预期在链接过程中它会失败时,它似乎有效
file5.c:
#include <stdio.h>
#include "var.h"
int a = 20;
int main() {
printf("\n File5.c a = %d", a);
test();
return 0;
}
file6.c:
#include <stdio.h>
#include "var.h"
int test() {
printf("\n File6.c a = %d",a);
}
var.h
int a;
由于我在所有头文件中都包含var.h
而没有extern,int a
将包含在.c
文件中,并且在链接期间,编译器应该抛出警告或错误消息但是它编译文件没有任何问题。
var.h
不应该有以下extern int a
?
答案 0 :(得分:2)
通常最好是标头使用extern int a;
。另请参阅How do I share a variable between source files in C?
标准说:
ISO / IEC 9899:2011§6.9.2外部对象定义
<强>语义强>
¶1如果对象的标识符声明具有文件范围和初始化程序,则 声明是标识符的外部定义。¶2具有没有初始化程序的文件范围的对象的标识符声明,和 没有存储类说明符或存储类说明符
static
,构成一个 暂定定义。如果翻译单元包含一个或多个临时定义 然后,标识符和转换单元不包含该标识符的外部定义 行为就像翻译单元包含该文件范围声明一样 标识符,具有复制类型,如翻译单元的末尾,带有初始化程序 等于0。
因此,标题中的内容是变量的暂定定义。在file5.c
的翻译单元(TU)结束时,您不再有一个暂定的定义; int a = 20;
指定的“外部定义”已指定。在file6.c
的TU结束时,您的定义等同于int a = 0;
。
当您尝试关联file5.c
和file6.c
时,您应该遇到a
的多个定义。但是,附件J的标准中有一个共同的扩展:
J.5.11多个外部定义
¶1对象的标识符可能有多个外部定义,用或 没有明确使用关键字
extern
;如果定义不同意或不同 一个被初始化,行为未定义(6.9.2)。
您的编译器提供了§J.5.11标识的扩展名,因此(合法地)不会抱怨。
580