C中对变量取址时,系统内部经过了怎样的一个过程?
知道 &
取址操作是
每一个变量标识符在编译期间,编译器会为它们创建一个符号表,其中存放着变量标识符相应的各种属性,如类型、地址标识等
那么问题来了:
- 每创建一个变量就要创建一个符号表的话,是不是会占用很大的内存?
- 整个创建变量并取址的完整过程在系统里是怎么进行的?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
反编译一下,或者用 gdb 就知道了。
可能是原文的误解,“每一个变量标识符在编译期间,编译器会为它们创建一个符号表,其中存放着变量标识符相应的各种属性,如类型、地址标识等”,这里面的他们,值得是所有的变量,而每个变量这是符号表里面的一个符号而已,所以,不是“为每个变量创建一个符号表”。
占用的内存会大,也可能很大,但是一般优秀的编译器都会优化。
而且,注意这段话里面的一个词语——在编译期间。
第二个问题,读读汇编语言里面的寻址,大概就明白了。
在C语言中,每个变量其实都是地址的一个别名。这个地址可能是
0x1002
,为了容易记忆,我们就给他起了一个名字,叫a
。其实,
a
就是0x1002
,0x1002
就是a
。这个语言大概会编译成
意思是把
a
放入0x1002
的地址里面。当我们使用变量时,其实使用的是地址里面的具体值。这个值是二进制的01串,这个值具体是多少,取决于数据类型。
对于指针操作呢,则直接操作的地址
这句话定义了一个变量
p
,p
是一个整数,p
的地址可能是0x1024
, 在这个地址里面,存放着a
(注意,不是a
地址里面的值,而是0x1002
)。为了便于理解,简化了好多。
这就是静态语言和动态语言的区别,静态语言编译之后,在内存里将只存在指针。
简单概括一下吧。对全局变量取址的话,汇编代码会直接有一个立即数在里面,作为地址。这个立即数是链接时候确定的。
局部变量的话,编译器首先会在栈上给他留个空间,否则没有地址,然后以ebp减偏移的方式去计算,偏移在编译这段函数的时候就计算好了。编译之后的代码里没有变量名字,所以不可能有根据名字去地址这样一个操作,顶多用lea做一下运算。
建议看看《csapp》,前半部分有讲。