Chinaunix首页 | 论坛 | 博客
  • 博客访问: 52530
  • 博文数量: 15
  • 博客积分: 481
  • 博客等级: 下士
  • 技术积分: 195
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-08 22:29
文章分类

全部博文(15)

文章存档

2013年(5)

2012年(1)

2009年(4)

2008年(5)

分类: LINUX

2013-03-22 13:50:16

1符号分类
三种symbol,
两种全局symbol
1 本模块中定义的可用于其它模块的
2 引用其它模块的
一种局部symbol
不可用于其他模块(static 修饰的变量 函数等)
\\对于编译器产生的relocatable object file中的symbol在C语言中包括(全局变量,函数体中static修饰的变量,函数名,section名,文件名...) #~:readelf -s a.out  
编译器仅保证第三种symbol(static local symbol)定义的唯一性,而对于全局变量,交给链接程序处理ld.

2ld对于符号变量的解释
At compile time, the compiler exports each global symbol to the assembler as either strong or weak, and the assembler encodes this information implicitly in the symbol table of the relocatable object ?le. Functions and initialized global variables get strong symbols. Uninitialized global variables get weak symbols.
符号变量分为强变量和弱变量,对于已初始化的为强变量,反之为弱变量
Rule 1: Multiple strong symbols are not allowed.
? Rule 2: Given a strong symbol and multiple weak symbols, choose the strong symbol.
? Rule 3: Given multiple weak symbols, choose any of the weak symbols.
eg:

点击(此处)折叠或打开

  1. [michael@master chap_linking]$ cat love.c f.c
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. char s='h';
  5. char a='a';
  6. char t='t';
  7. char e='e';
  8. void f(void);
  9. int main(){
  10.         f();
  11.         printf("I %c%c%c%c you!\n", s, a, t, e);
  12.         return 0;
  13. }
  14. //f.c
  15. #include <stdio.h>
  16. float s;
  17. int f(void){
  18.         s = 72734845349891911188480.0;  //机器数据little-endian表示,根据浮点数二进制表示规则,可算出s地址空间从下往上是"love"
  19.         return 0;
  20. }
  21. [michael@master chap_linking]$ gcc love.c f.c && ./a.out
  22. I love
解释:虽然对全局变量s的定义不同,但是却是可以通过的。
首先在编译的时候,由于s是全局变量,编译器不会理会它们是否定义唯一,仅检查对其操作是否符合规则printf("I %c%c%c%c you!\n", s, a, t, e); s = 72734845349891911188480.0;都是符合规则的,故编译通过;
在链接的时候,需要对全局变量进行唯一定义,由于两个模块中的s一个是强变量,一个是弱变量,根据规则,f.c中的s会采用love.c中s的地址,故编译通过。
运行的时候,由于s,a,t,e都是已初始化的全局变量,其在linux内存中处于.data区域,内存地址是由下往上的,调用f函数时,会改写s,a,t,e分别为l o v e.
(当然s也可以改成指针的形式

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. //char s='h';
  4. //char a='a';
  5. //char t='t';
  6. //char e='e';
  7. char str[]="hate"
  8. char *pstr = str;  //如直接用char *pstr="hate"; 由于"hate"指向内存中.rodata部分,故不能改写。由于数组名是地址常量,也不能直接用数组,要做个小变换。
  9. void f(void);
  10. int main(){
  11.         f();
  12. // printf("I %c%c%c%c you!\n", s, a, t, e);
  13.         printf("I %s you!\n", pstr);
  14.         return 0;
  15. }

  16. #include <stdio.h>
  17. float *pstr;
  18. int f(void){
  19.         float *p = pstr;
  20.         *p = 72734845349891911188480.0;
  21.         return 0;
  22. }


阅读(1274) | 评论(0) | 转发(0) |
0

上一篇:获取ip和mac地址的C程序

下一篇:没有了

给主人留下些什么吧!~~