C语言中的强符号和弱符号
C语言真的很奇怪,各种你想不到的问题都会出现,但是仔细分析这个问题,无不很有道理,这些都不是C语言的漏洞,而是这门语言的强大之处。
首先介绍一下强符号和弱符号。
当多个C文件需要一起编译运行的时候,就会有强弱符号的问题。为什么会有多个C文件一起编译呢?这就的说起链接Linking,关于Linking你可以去看这个。
在一起编译的C文件中,如果存在多个变量名相同的全局变量(Global,一定是全局的,并且不能是static的),如果他们都没有初始化,那么他们就是虚符号。如果有一个初始化了,那么他就是强符号,其他的就是虚符号。如果存在多个初始化的变量,那么就会报错。对于第一种情况,系统会有某种机制选取一个作为整个的全局变量,这种机制说明了,它会按照一种顺序选取,而不是随机选取。这种顺序可能是编译时候的文件顺序,也可能是别的。第二种情况就比较可爱了。直接使用强符号作为全局变量。第三种是不允许的。
好了下面进行测试:
编译方法:
gcc –o testa.c b.c
运行方法:
./test
对于第一种情况,编写代码如下:
第一个文件:
$ vim a.c
#include<stdio.h>
int x=1234,y=1234;
int main(){
f();
printf(“x = %d, address is %x\n”,x,&x);
printf(“y = %d, address is %x\n”,y,&y);
return 0;
}
第二个文件:
$vim b.c
double x;
void f(){
x = -12233.333333333333;
}
这个测试程序的目的很简单,就是两个C文件中出现了相同的变量x,在a.c中进行了初始化,因此在a.c中就是强符号,在内存中就占用4个字节,同样y也占用4个字节。但是在b.c中,f()函数将-0.0赋值给x,这可是一个double啊。于是就将y占用的4个字节也给占领了。
测试结果:
x = -1431655949,address is 601040
y = -1060641622,address is 601044
简单分析一下:
从地址可以看出,x占用了4个字节,调用f()函数后,将double赋值给x,就把y也给污染了。打印出来的数据不再分析,这涉及到浮点数在内存中的存储方式。
换测试程序如下:
第一个文件:
$vim a.c
#include<stdio.h>
int x,y;
int main(){
f();
printf(“x = %d, address is %x\n”,x,&x);
printf(“y = %d, address is %x\n”,y,&y);
return 0;
}
第二个文件:
$vim b.c
double x = -0.0;
f(){
x = -0.0;
}
这样在b.c中的x就成了强符号,那么内存分配时,就会给他8个字节。
测试结果如下:
x = 0, address is 601048
y = 0, address is 601050
这,让我始料未及啊,怎么就成2个字节了呢。呵呵,我承认我是个渣货,突然明白,这是16进制!!!48到50就是8个字节有48 49 4a 4b 4c 4d 4e 4f。
再换测试程序如下:
第一个文件:
$vim a.c
#include<stdio.h>
int x,y;
int main(){
f();
printf(“x = %d, address is %x\n”,x,&x);
printf(“y = %d, address is %x\n”,y,&y);
return 0;
}
第二个文件:
$vim b.c
double x;
f(){
x = -0.0;
}
测试结果如下:
x = 0, address is601048
y = 0, address is601050
意味着编译器选择了double型的分配了内存,我怀疑是编译顺序的问题,但是调换为
gcc –o test b.c a.c
结果还是这样。
好了,总结一下。
当多个文件一起编译时,全局变量就变得很危险,非常危险。你可以有下面几种解决方案:
1、上策:想办法消除全局变量。全局变量会增加程序的耦合性,对他要控制使用。如果能用其他的方法代替最好。
2、中策:实在没有办法,那就把全局变量定义为static,它是没有强弱之分的。而且不会和其他的全局符号产生冲突。至于其他文件可能对他的访问,可以封装成函数。把一个模块的数据封装起来是一个好的实践。
3、下策:把所有的符号全部都变成强符号。所有的全局变量都初始化,记住,是所有的,哪怕初始值是0都行。如果一个没有初始化,就可能会和其他人产生冲突,尽管别人初始化了。(自己写代码测试一下)。
4、必备之策:GCC提供了一个选项,可以检查这类错误:-fno-common。
如果你觉得这很低端,你可以去http://blog.csdn.net/astrotycoon/article/details/8008629这。他写的很高端。
参考文献:
http://blog.csdn.net/astrotycoon/article/details/8008629