我有一个主程序:
#include <stdio.h>
extern int a;
int main (int argc, char ** argv) {
int i;
printf ("Hello %p, %p\n", & i, & a);
return 0;
}
和一个单独的文件foo.c
,其中包含我对变量a
的定义:
int a;
如果我这样建造:
clang -c main.c foo.c
clang main.o foo.o
./a.out
一切都很好。但是,如果我执行以下操作:
ar rvs bar.a foo.o
我收到警告,我不明白
r - foo.o
warning: /<elided>/ranlib:
warning for library: bar.a the table of contents is empty
(no object file members in the library define global symbols)
所以我检查了我的图书馆,确保我的符号在那里
nm bar.a
bar.a(foo.o):
0000000000000004 C _a
然后我做
clang main.o bar.a
我收到以下错误
Undefined symbols for architecture x86_64:
"_a", referenced from:
_main in main-5121f1.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我错过了什么?
答案 0 :(得分:1)
我认为问题在于int a;
中的foo.c
是一个暂定的定义。它在C
的输出中标记为nm
(常用)。如果你明确初始化(为了0
的一致性;为了确保测试目的而使用一些非零值),我相信你没有问题。
我并不完全相信,因为在TU结束时,暂定的定义应转换为定义:
ISO / IEC 9899:2011§6.9.2外部对象定义
¶2具有没有初始化程序的文件范围的对象的标识符声明,和 没有存储类说明符或存储类说明符静态,构成一个 暂定的定义。如果翻译单元包含一个或多个临时定义 然后,标识符和转换单元不包含该标识符的外部定义 行为就像翻译单元包含该文件范围声明一样 标识符,具有复制类型,如翻译单元的末尾,带有初始化程序 等于0。