答案 0 :(得分:2)
技术上应该存在,但是这种使用已经存在多年并且无法根除(已经尝试过;一些供应商经常决定使其成为错误,并在大约一百个左右的错误报告之后恢复)。小心翼翼地,.h
文件应声明extern
和一个 .c
/ .cpp
文件应该定义它。
简而言之,当您未指定顶级变量的链接(static
,extern
等)时,它会被声明为“常见”。在链接时,如果对该变量的所有引用都是相同的大小(和类型,如果可用),那么它将被分配一次,并且所有引用都指向它。如果链接器为同一个变量找到不同的大小/类型/链接,则会抛出错误。
jinx:1714 Z$ cat foo.h
int foo;
extern void bar();
jinx:1715 Z$ cat foo.c
#include "foo.h"
int
main(int argc, char **argv)
{
bar();
return 0;
}
jinx:1716 Z$ cat bar.c
#include "foo.h"
void
bar(void)
{
return;
}
jinx:1717 Z$ gcc -Wall foo.c bar.c -o foo
jinx:1718 Z$ ./foo
jinx:1719 Z$ _
请注意,int foo
被多重定义完全没有错误。 这个就是我一直想说的。
答案 1 :(得分:1)
此struct list_head source_list;
字段在其他结构中声明,因此它们不是符号。
其他(顶级)结构的声明具有不同的名称,所以它也可以。
修改强>
请注意,此标头的所有变量都标有extern
。
答案 2 :(得分:1)
这个术语是“暂定”:
。的标识符声明 没有文件范围的对象 初始化程序,没有 存储类说明符或与 存储类说明符static, 构成一个 暂定的定义。如果翻译单元包含一个或多个 暂定的定义 标识符,并且翻译单元不包含外部 那个标识符的定义 行为就像翻译单元包含一个 文件范围声明 标识符,复合类型截至 翻译单元,带初始化程序 等于0。
所以这在C中有很好的定义(但经常不赞成)。
答案 3 :(得分:0)
确实应该有extern
。但是,该变量没有明确的定义,因此编译器会将其标记为extern。
如果你有
,你会收到链接器错误struct list_head source_list = { 0 };
...因为 每个翻译单元定义一次符号(因此链接器会抱怨)。