强符号与弱符号

我们在编程当中肯定会碰到一种情况叫符号重定义。
当多个目标文件中含有相同名字的全局符号的定义时,那么将这些文件进行链接的时候将会出现符号重定义的错误。比如,我在a.c和b.c都定义了一个全局的整型变量int g_lobal,并将他们初始化,注意,一定要两个两个变量都进行初始化才会出现重复定义的情况。那么这个时候链接的时候肯定会报重复定义的错误。
a.c

#include<stdio.h>
#include"b.h"
int a= 20;
int main()
{
    
    
}

b.c

#include<stdio.h>
int a = 10;

b.h

#include <stdio.h>
extern int a;

执行结果:提示了a重复定义。
在这里插入图片描述
强符号在c/c++当中,编译器默认函数和初始化了的全局变量为强符号,而未初始化的全局变量为弱符号。

当然,我们也可以通过gcc的“attribute((weak))”来定义任何一个强符号为弱符号,比如:

#include<stdio.h>
#include"b.h"
int i = 10; //i是强符号
_attribute_((weak)) a= 20;//现在a是弱符号
int main()//main是强符号
{
    
    
}

要注意的是,强符号和弱符号是针对定义来决定的,而不是引用,比如:

extern int b;//b既不是强符号也不是弱符号
//b只是一个外部变量的引用

针对强符号和弱符号,链接器会按照如下的规则去处理:

规则1:不允许强符号被定义多次。
规则2:如果一个符号在某个文件当中是强符号,在其它文件是弱符号,那么链接时将选择强符号
规则3:如果一个符号在所有的目标文件当中都是弱符号,那么链接时将选择占用空间最大的那个。
比如,a.c当中有int a;占4个字节,b.c当中有double a;占8个字节,链接时,将选择double a;

针对上面的规则,大家可以写例程进行验证。

对于上面说的强符号和弱符号来说,,如果是强符号,那么在链接时必须要找到该强符号的定义,这称为强引用,也就是strong reference,不然会报未定义的错误,比如:

#include<stdio.h>
void dd();
int main()
{
    
    
	dd();
}

在这里插入图片描述
因为dd是强符号,而在链接时,必须要找到该符号的定义。

而相对的是弱引用,在处理弱引用时,如果有定义,那么就正常处理,如果没有,那么也不会报错。
#include<stdio.h>
//attribute((weakref)) void dd();
int attribute((weak)) weak2 = 2;
int main()
{
}
在这里插入图片描述
编译正常。

猜你喜欢

转载自blog.csdn.net/qq_38158479/article/details/119964396