C 语言中 标识符的使用机制

来源:互联网 发布:统一软件过程图 编辑:程序博客网 时间:2024/05/22 01:54
   将源文件编译成可执行程序,需经历四个过程 
  • 预编译  将头文件插入到源文件中,删除注释,替换宏...等等
  • 编译    将C语言的源文件编译成汇编语言源文件
  • 汇编    将汇编语言源文件传化成机器语言文件,即目标文件
  • 链接     将目标文件链接成可执行文件
   前三个过程相对而言,不是很复杂。重点放在链接过程如何将多个目标文件链接成可执行文件的。linux下目标文件和可执行文件都采用的是ELF格式,每个ELF文件都包含多个section,如:.test.data .rodata .rela.text .symtab...。其中目标文件中的重定位表(如:.rela.text)和符号表(.symtab)在链接过程中起着非常重要的作用。连接器根据中重定位表来确定目标文件中需要重定位处的地址--全局标识符在指令中的位置,并根据符号表来查找标识符对应内存区的地址。
    重定位表包含结构Elf64_Rel的对象数组,每个数组元素对应一个需要重定位的地址。定义在/usr/include/elf.h 
typedef struct
{
  Elf64_Addr   r_offset;            
  Elf64_Xword   r_info;             
} Elf64_Rel;

   符号表包含Elf64_Sym的对象数组,每个数组元素对应一个标识符,定义在/usr/include/elf.h 
typedef struct
{
  Elf64_Word   st_name;              
  unsigned char st_info;             
  unsigned char st_other;            
  Elf64_Section st_shndx;            
  Elf64_Addr   st_value;            
  Elf64_Xword   st_size;             
} Elf64_Sym;

   下面来看一个实例:
test.c
  1#include<stdio.h>
 
  3 void main()
  4 {
  5 int a=1,b[2]={2,3};
  6 void (*func)(void);
  7 func=&main;
 
  9 printf("the value of a is %x\n",a);
 10 printf("the value of &ais %x\n\n",&a);
 11 
 12 printf("the value of b is %x\n",b);
 13 printf("the value of &bis %x\n",&b);
 14 printf("the value of *b is%x\n\n",*b);
 15 
 16 printf("the value of func is%x\n",func);
 17 printf("the value of&func is %x\n",&func);
 18 printf("the value of *func is%x\n\n",*func);
 19 
 20 printf("the value of main is%x\n",main);
 21 printf("the value of&main is %x\n",&main);
 22 printf("the value of *main is%x\n",*main);
 23 }

gcc -o test test.c
./test

the value of a is 1
the value of &a is 817bbfc

the value of b is 817bbe0
the value of &b is 817bbe0
the value of *b is 2

the value of func is 4004f4
the value of &func is 817bbf0
the value of *func is 4004f4

the value of main is 4004f4
the value of &main is 4004f4
the value of *main is 4004f4

由此可见:
  1. 对于变量,标识符 表示变量值;&标识符 表示变量的虚拟地址。
  2. 对于数组,标识符 表示数组的起始地址; &标识符 还是表示数组的起始地址;*标识符表示第一个元素值
  3. 对于函数,标识符、&标识符、*标识符都表示函数的起始地址,都是取自Efl64_Sym.st_value
  4. 对函数指针变量,标识符、*标识符 表示函数的起始地址,&标识符 表示变量地址
原创粉丝点击