在编译的时候,编译器向汇编器输出每一个全局符号,或是强(strong)或者弱(weak),而汇编器把这个信息隐含地编码在可重定位目标文件的符号表里,函数和已初始化的全局变量是强符号,未初始化的全局变量是弱符号。 根据强弱符号的定义,UNIX连接器使用下面的规则来处理多重定义的符号: 函数
1. 不容许有多个强符号 编码
2. 若是有一个强符号,多个弱符号,那么会选择强符号 spa
3. 若是有多个弱符号,那么从这些弱符号中任选一个 编译器
如下是几个小例子: io
<1> 编译
int main() int main() 变量
{ { di
return 0; return 0; 文件
} } co
连接器会提示强符号main被重复定义。
<2>
/* foo2.c */ /* bar3 */
#include <stdio.h> int x;
void f(); void f()
int x = 123; {
int main() x = 132;
{ }
f();
printf("x = %d\n", x);
return 0;
}
在运行时,函数f会将X的值改成132, 这会给main函数的使用者带来不受欢迎的意外!!!注意,连接器一般不会代表它检测到多个X的定义!!!
执行: ./foo
最后会输出132
<3> 若是x是弱定义,也会发生相似2的问题
* foo2.c */ /* bar3 */
#include <stdio.h> int x;
void f(); void f()
int x ; {
int main() x = 132;
{ }
x = 123;
f();
printf("x = %d\n", x);
return 0;
}
输出x = 132
因此GCC有 -fno-common这个选项调用连接器,能够在遇到多重定义的全局符号时给出warning