C语言中的强符号和弱符号

一、强弱符号

强弱符号针对的是处于同一工程下在不同源文件下定义的全局变量符号,链接器只处理global的符号而不处理local的符号。链接的核心是符号的重定位,在符号引用的地方找到符号定义的地方,包括函数产生的符号和全局变量产生的符号。

强符号:函数和初始化的全局变量所生成的符号。
弱符号:未初始化的全局变量所生成的符号。

很多情况下写出的代码会出现链接的错误,符号重定义,这是因为在不同的源文件中定义了同名的全局变量并且都进行了初始化。

//a.c
int gdata = 10;
//b.c
int gdata = 20;
#include<stdio.h>
int main(){
    printf("gdata = %d\n",gdata);
    return 0;
}

这里写图片描述
这是很多新手容易犯的错误,若将a.c或b.c中全局变量gdata只初始化一次,则不会出现链接错误,并且会链接成功。那么新的问题是:
(1)出现强符号和弱符号,选择哪一个?
(2)若出现多个同名的强符号,最终怎么选择?
(3)若出现多个同名的弱符号,最终会怎么选择?

显然需要这样的一套规则来约束这些可能存在的问题。

二、强弱符号的使用规则

(1)如果出现多个强符号,最终会出现链接错误即符号的重定义。
(2)如果出现强符号和弱符号,编译器最终会选择强符号。
(3)如果出现多个同名弱符号,编译器最终会选择内存占用量最大的那个符号。

一个有趣的小例子再看强弱符号:

//a.c
int x;
void func(){
    x = 20;
}
//b.c
#include<stdio.h>
short x = 10;
short y = 10;
extern void func();
int main(){
    func();
    printf("x = %d,y = %d\n",x,y);
    return 0;
}
//试问输出的x和y分别是多少,大家可以自己先想一下,看看自己的答案。

执行结果:
这里写图片描述
和大家心中的答案是否一致呢?
有很多人会有疑问,为什么y输出的不是10,而是0呢?
源文件是独立进行编译的

//a.c
int x;//弱符号
void func(){
    x = 20; //往x的内存上写20,写4个字节   编译阶段就完成的
}
//b.c
#include<stdio.h>
short x = 10;//强符号   14 00 00 00最终将y覆盖为0
short y = 10;
extern void func();
int main(){
    func();//链接的完成选择强符号
    printf("x = %d,y = %d\n",x,y);
    return 0;
}

在 gcc中,可以通过__attribute__((weak))来强制定义任何一个符号为弱符号。

猜你喜欢

转载自blog.csdn.net/ASJBFJSB/article/details/81267934