C语言中的弱符号与强符号,强引用与弱引用

强符号和弱符号


       在编程中碰到一种情况叫符号重复定义。多个目标文件中含有相同名字的全局变量的定义,那么这些目标文件链接的时候就会出现符号重复定义的错误。比如在目标文件 A 和目标文件 B 都定义了一个全局整形变量global,并且都初始化,那么当 A 和 B 链接时会报错:

    multiple definition of 'global'

       对于C/C++来说,编译器默认函数和初始化了的全局变量为强符号,未初始化的全局变量为弱符号。我们也可以通过GCC的"__attribute__((weak))"来定义任何一个强符号为弱符号。

#include <stdio.h>
 
extern int temp;        // 非强符号也非弱符号
 
int weak;               // 弱符号
int strong = 1;         // 强符号
__attribute__((weak)) int weak2 = 2;    // 弱符号
int main()
{
    //代码
    return 0;   
}

它们有三条使用规则:

规则1:不允许强符号被多次定义。

规则2:如果一个符号在某个目标文件中是强符号,在其他文件中都是弱符号,那么选择强符号。

规则3:如果一个符号在所有的目标文件中都是弱符号,那么选择其中占用空间最大的一个。


强引用和弱引用


       系统中的某些扩展功能模块可能时有时无,如果要求系统在两种情况下都能够正常的工作,那么就需要在功能模块不存在时,主程序对这些引用不能报错。

       如果模块A引用模块B的一个函数时,如果模块B的这个函数不存在,模块A不报错。

       强引用:目标文件引用了外部符号,在链接时若未找到定义则报错;则对该外部符号的引用为强引用;

       弱引用:目标文件引用了外部符号,在链接时若未找到定义也不报错;则对该外部符号的引用为弱引用

       默认的模块中对所有对外部符号的引用在链接时都是强引用,该符号必须能够被正确的“决议”(或者说“绑定”),否则连接器就会报错,GCC中通过 __attribute__((weak))关键字(也可以用__attribute__((weakref)),具体区别可以自己去研究)显示的对一个外部符号的引用定义为弱引用,这样,即使连接的时候该符号没有正确的找到定义,链接器也不会报错,而只是将该符号的值置为0。但这样得到的可执行程序在执行时会报错,因为当调用弱引用时,弱符号的地址为0,属于非法访问。因此,在程序中调用一个外部符号时,应该先判断其值是否为0,若不为0再调用。如:

 #include <stdio.h>
__attribute__((weak)) void foo();  
  
int main()  
{  
    if(foo) 
    {
        foo();
    }
    return 0;
}

总结


       强弱符号而进一步引入的强弱引用。书中关于强弱引用的概述是对于强引用若未定义则链接时肯定会报错,而对于弱引用则不会报错,链接器默认其为0(这一点对于函数好理解,即函数符号所代表入口地址为0;对于变量就要注意了,既然是引用那自然就是地址了,所以同函数一样变量的地址为0而不是变量的值为0)。在定义和声明处指定的函数名、变量名即为对应的符号,而在代码其它处调用函数或使用变量时,则把函数和变量名看作引用,这样一来符号和引用在代码层面上其实就是一个东西,只是根据环境而叫法不同而已。那么强符号对应强引用,弱符号对应弱引用。

       有上面的强弱引用的特点可看出,当一个函数为弱引用时,不管这个函数有没有定义,链接时都不会报错,而且我们可以根据判断函数名是否为0来决定是否执行这个函数。这样以来,包含这些函数的库就可以以模块、插件的形式和我们的引用组合一起,方便使用和卸载,并且由于强符号可以覆盖弱符号和强弱符号与强弱引用的关系可知,我们自己定义函数可以覆盖库中的函数,多么美妙。


  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值