首先上代码和结果:
代码:
#include <stdio.h>
int k;
int k;
int main()
{printf("addr of k = %p\n", &k);printf("value of k = %d\n", k);return 0;
}
结果:
addr of k = 00408074
value of k = 0
问题:
由结果可得,系统已为全局变量k开辟了内存空间(因为可以打印到变量k的地址),并且为该变量拥有初值0
可知,int k;
为定义了全局变量k,但是为什么k能被定义两次呢?
分析:
- 符号
在分析前,先来说明一下符号这个概念。在c程序生成可执行文件前,有以下步骤:预编译 -> 编译 -> 汇编 -> 链接
在生成.exe文件前的最后一步,即在链接步骤中,由项目中各个.c文件生成的.o文件(目标文件)会基于其符号表中的符号,来将各个.o文件链接在一起,生成可执行文件
下面用指令查看一下.o文件中的符号表
/* sym.c */
#include <stdio.h>
int sym = 1024;
int func_sym()
{return 0;
}int main()
{return 0;
}
指令:
gcc sym.c -o sym.o // 生成sym.o文件
nm sym.o // 查看.o文件的符号表
符号表部分内容如下:
…(省略)
00401a40 T ___main
00404004 D _sym
00401410 T _func_sym
可以看到符号表有变量sym,函数main和函数func_sym的符号
- 强/弱符号
对于C/C++语言来说,编译器默认函数和初始化了的全局变量为强符号,未初始化的全局变量为弱符号。当然也可以通过
来定义一个强符号为弱符号。
通过下面的例子来看看哪些是强符号,哪些是弱符号
#include<stdio.h>
int weak; // 定义但未初始化全局变量,弱符号
int strong = 1024; // 定义且已初始化全局变量,强符号
__attribute__((weak)) int weak1 = 2222; // 使用标识修饰的弱符号
int main(void)
{ printf("test\n"); return 0;
}
注意,这里的强符号与弱符号都是针对定义来说的。
原理:
同名时,用哪个?变量重名时,链接器有它的处理方式:
- 强符号不允许重复
- 有一个强符号和多个弱符号,使用强符号
- 多个弱符号,则随意选择一个
由3.可知,在
#include <stdio.h>
int k;
int k;
int main()
{printf("addr of k = %p\n", &k);printf("value of k = %d\n", k);return 0;
}
中,第一个k和第二个k均为未初始化的全局变量,所以均为弱符号;所以随意选择一个
参考:
- 函数或全局变量重复定义时会怎样?
- C语言中的强符号与弱符号