C/C++中的强符号和弱符号
C/C++中的强符号和弱符号
先看如下场景
// 在1.c中定义了全局变量 int g = 1; int g2;
同时
// 在2.c中也定义了全局变量 int g = 1; double g2;
对上边C文件编译时会报符号重复定义(Multiple Definition)的错误,这是因为在多个源文件中定义了同名的全局变量,且都已初始化。报错如下
2.o: multiple definition of `g' 1.o: first defined here
在C中,默认情况下,编译器认为函数和已初始化的全局变量为强符号(Strong Symbol),未初始化的全局变量为弱符号(Weak Symbol)。强符号是因拥有已确定的初始化数据,变量有值,函数有函数体;弱符号则是因符号还未被初始化,无确定数据,只是个声明。
链接器对重复定义变量(强/弱符号)的处理规则:
- 不能定义多个强符号,即不同.o目标文件里变量/函数不能重复定义,若有多个同名强符号,链接器报符号重定义的错误。
- 若一符号在其中一个目标文件中是强符号,其他是弱符号(如只声明,无初始化),则选择强符号。
- 若一符号在所有目标文件中都是弱符号,则选占内存空间最大的一个。如上边例子的g2会占8字节,可见若出问题则很难排查。(此点参考其他博客资料,最新编译器验证是不成立的,见下文例子)
特注:上边第3点在实测中不一定对,用sizeof会是本文件变量的内存大小。
//gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) // main.c #include<stdio.h> int w2; int main() { printf("sizeof(w2)=%ld in main.c", sizeof(w2)); func(); return 0; } //test.c #include<stdio.h> double w2; void func() { printf("sizeof(w2)=%ld in test.c\n", sizeof(w2)); } //编译 gcc main.c test.c //运行结果: sizeof(w2)=4 in main.c sizeof(w2)=8 in test.c //同样这个例子,用g++编译的话,则会报重复定义的错误了 /tmp/ccqUe8kE.o:(.bss+0x0): `w2'被多次定义 /tmp/cczTldSS.o:(.bss+0x0):第一次在此定义 collect2: error: ld returned 1 exit status
使用gcc编译,可用_attribute_((weak))强制定义一符号为弱符号,可用于解决重复定义的报错(用于调试用,实际工程还是别这么干了)。见如下例子:
extern int e1; //引用外部变量,非强符号也非弱符号,作用是告诉编译器别报未定义,这个变量在链接时能找到。 int w1;//弱符号 __attribute__((weak)) int w2 = 1; //弱符号 __attribute__((weak)) void func() { //弱符号,如果func函数在其他地方也被定义了,不加__attribute__((weak))会报Multiple Definition错误 printf("弱符号函数"); } int s1 = 1;//强符号 void main() { printf("强符号"); }
弱符号主要用于解决一些库的冲突或引入一些库,防止符号冲突。再看个上面列的第二规则的例子(注意是两个c文件):
//gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) //以下内容是test.c内容 #include<stdio.h> int w1 = 2; void func() { printf("weak symb =func in test\n"); } //以下是main.c内容 #include<stdio.h> __attribute__((weak)) int w1 = 1; __attribute__((weak)) void func() { printf("weak symb =func in main\n"); } int main() { printf("w1=%d\n", w1); func(); return 0; } //编译: gcc main.c test.c 运行结果,打印出强符号的值 (g++ main.c test.c编译的结果也一致) w1=2 weak symb =func in test
当然,_attribute_((weak))只对链接器有效,对编译器无效,在编译器没有强/弱符号之分,如在同一文件内,定义两个同名变量,则报重复定义错误,如例子
#include<stdio.h> __attribute__((weak)) int w1 = 1; int w1 = 2; int main() { printf("w1=%d\n", w1); return 0; } //编译gcc test_sam.c error: redefinition of ‘w1’ int w1 = 2; ^~ note: previous definition of ‘w1’ was here __attribute__((weak)) int w1 = 1;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!