首页 > C中对变量取址时,系统内部经过了怎样的一个过程?

C中对变量取址时,系统内部经过了怎样的一个过程?

知道 & 取址操作是

每一个变量标识符在编译期间,编译器会为它们创建一个符号表,其中存放着变量标识符相应的各种属性,如类型、地址标识等

那么问题来了:

  1. 每创建一个变量就要创建一个符号表的话,是不是会占用很大的内存?
  2. 整个创建变量并取址的完整过程在系统里是怎么进行的?

代码中的变量在“编译”的时候会全部转换为指针进行存储。

这就是静态语言和动态语言的区别,静态语言编译之后,在内存里将只存在指针。

指针就是变量,变量就是指针。


简单概括一下吧。对全局变量取址的话,汇编代码会直接有一个立即数在里面,作为地址。这个立即数是链接时候确定的。
局部变量的话,编译器首先会在栈上给他留个空间,否则没有地址,然后以ebp减偏移的方式去计算,偏移在编译这段函数的时候就计算好了。编译之后的代码里没有变量名字,所以不可能有根据名字去地址这样一个操作,顶多用lea做一下运算。
建议看看《csapp》,前半部分有讲。


反编译一下,或者用 gdb 就知道了。

每创建一个变量就要创建一个符号表的话

可能是原文的误解,“每一个变量标识符在编译期间,编译器会为它们创建一个符号表,其中存放着变量标识符相应的各种属性,如类型、地址标识等”,这里面的他们,值得是所有的变量,而每个变量这是符号表里面的一个符号而已,所以,不是“为每个变量创建一个符号表”。

占用的内存会大,也可能很大,但是一般优秀的编译器都会优化。

而且,注意这段话里面的一个词语——在编译期间

第二个问题,读读汇编语言里面的寻址,大概就明白了。

在C语言中,每个变量其实都是地址的一个别名。这个地址可能是 0x1002,为了容易记忆,我们就给他起了一个名字,叫 a

其实,a 就是 0x10020x1002 就是 a

int a = 4;

这个语言大概会编译成

MOV [1002h] 4   
; 4是立即数 
; []直接寻址

意思是把 a 放入 0x1002 的地址里面。

当我们使用变量时,其实使用的是地址里面的具体值。这个值是二进制的01串,这个值具体是多少,取决于数据类型。

对于指针操作呢,则直接操作的地址

int *p = &a;

这句话定义了一个变量 p, p 是一个整数,p 的地址可能是 0x1024, 在这个地址里面,存放着 a(注意,不是 a 地址里面的值,而是 0x1002)。

MOV P 1024h  
MOV [P] 1002h
; 1024是立即数, 
; []直接寻址

为了便于理解,简化了好多。

【热门文章】
【热门文章】