在编译链接的时候链接器需要将符号解析为相应的对象。

首先有这样几个原则:在同一个命名空间内的符号,是相互可见的。

这里的命名空间是一个很抽象的概念,例如一个function本身可以看作一个命名空间,它所有的局部变量,只在内部可见;函数执行完毕后由于栈平衡的作用使得这些局部变量全部销毁。显然可以推测,对于局部符号以及被static修饰的符号,不会存在什么符号可见性的问题。

 

但是对于全局符号就完全不一样了。一个全局符号(例如全局变量)可能会在多处定义或者引用,编译器为了正确的处理这些关系,便定义了强弱符号和强弱引用的概念。

 

强符号:一个定义并且初始化过的全局符号。例如下面:

int strong = 0;

void  iamstrong() {}

 

弱符号:一个定义但是未初始化过的全局符号。例如:

int week;

 

强引用:对某个符号的显式引用。链接期间若该引用的定义不存在则会出错。

弱引用:基本上同强引用,但是链接期间若找不到该引用定义也不会报错。

 

下面这个程序:

void bar();

int main(void) {

bar();

return 0;

}

一般来说,如果直接编译链接,则会报bar符号找不到的链接错误。显然,这里的bar就是一个强引用。

利用GCC内置一个声明,将bar声明为弱引用,则编译链接会成功。如下所示:

__attribute__ ((weekref)) void bar();

 

但是这个程序运行的时候会报错,因为bar此时实际上是NULL(0)