1

我有一个主程序:

#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)

我错过了什么?

4

1 回答 1

2

我认为问题在于int a;infoo.c是一个暂定的定义。它C在 的输出中标记为(通用)nm。如果您显式初始化(​​为了0保持一致性;为了确保测试目的而使用一些非零值),我相信您不会有问题。

我并不完全相信,因为在 TU 结束时,暂定定义应该转换为定义:

ISO/IEC 9899:2011 §6.9.2 外部对象定义

¶2 具有文件范围的对象的标识符声明,没有初始化程序,没有存储类说明符或存储类说明符 static,构成暂定定义。如果翻译单元包含一个或多个标识符的暂定定义,并且翻译单元不包含该标识符的外部定义,则行为与翻译单元包含该标识符的文件范围声明完全相同,复合类型为翻译单元的末尾,初始化器等于 0。

另请参阅如何在 C 中的源文件之间共享变量?

于 2014-07-31T04:03:18.560 回答