【发布时间】:2011-03-23 11:58:04
【问题描述】:
【问题讨论】:
-
“编译单元”通常称为“翻译单元”。
标签: c symbols header-files
【问题讨论】:
标签: c symbols header-files
技术上应该有,但是这种用法已经存在多年并且不可能根除(已经尝试过;每隔一段时间就会有一些供应商决定将其设为错误,并在前一百个左右的错误报告后恢复)。学究式地,.h 文件应该声明它 extern 并且 one .c/.cpp 文件应该定义它。
简而言之,当您不指定顶级变量的链接(static、extern 等)时,它被声明为“common”。在链接时,如果对该变量的所有引用都具有相同的大小(和类型,如果可用),则分配一次并且所有引用都指向它。如果链接器发现同一变量的大小/类型/链接不同,则会引发错误。
编辑:这显然令人困惑。这里:
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 被多重定义的错误。 这是我一直想说的。
【讨论】:
module.h中的struct list_head source_list;是一个变量的定义?
binutils 的人们抱怨需要支持它的工作),这就是为什么经常有人试图杀死它。
module.h 中的 struct list_head source_list; 不是全局变量声明,因为它们发生在其他结构内(即 module_use 和 module)。
这个术语是“暂定定义”:
一个标识符的声明 具有文件范围但没有 初始化器,并且没有 存储类说明符或与 存储类说明符静态, 构成一个 暂定定义。如果翻译单元包含一个或多个 暂定定义 标识符,并且翻译单元不包含外部 该标识符的定义,然后 行为就像翻译单元包含一个 文件范围声明 标识符,复合类型截至 翻译单元,带有初始化器 等于 0。
因此,这在 C 中已得到很好的定义(但通常不受欢迎)。
【讨论】:
one or more tentative definitions for an identifier.
此struct list_head source_list; 字段在其他结构中声明,因此它们不是符号。
其他(顶级)结构的声明具有不同的名称,所以也可以。
编辑
请注意,此标头中的所有变量都标有extern。
【讨论】:
确实应该有一个extern。但是,该变量没有明确的定义,因此编译器会将其标记为 extern。
如果你有,你会得到一个链接器错误
struct list_head source_list = { 0 };
...因为这个确实为每个翻译单元定义了一次符号(因此链接器会抱怨)。
【讨论】: