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


                                                                             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

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值