请教一个很基础的变量内存分配问题

2021-08-01 18:26:29 +08:00
 yezheyu

我声明一个整型变量 a = 10

会在栈空间开辟一块内存来存 10 这个值,假设地址是 0x002

这也就意味着变量 a 的值的地址是 0x002,那么我想问下变量 a 本身存在哪?

程序是怎么知道 0x002 这个地址在命名空间中叫 a,总该有个地方存 a 吧?

是在栈区起始位置以类似 a:0x002 这种把变量名和其值的地址放在一起存起来吗?还是其它什么机制?

最近看了很多博客,都没提到这点,有老哥帮忙解释下吗?

4057 次点击
所在节点    程序员
44 条回复
zoharSoul
2021-08-01 18:31:35 +08:00
首先不一定是栈,
java 的可能在堆
felixin
2021-08-01 18:52:45 +08:00
汇编里没有变量的概念,所有用到 a 的地方都已经替换成了实际地址
ccde8259
2021-08-01 18:55:28 +08:00
栈帧里的本地变量表?
songlinliee
2021-08-01 18:59:04 +08:00
我的理解,在底层操作的时候会直接对地址操作,编译器会把变量转换成虚拟地址,然后通过地址转换器分配物理地址。
编译器负责根据软件逻辑来分配虚拟地址,MMU 负责管理实际物理内存。
wwhontheway
2021-08-01 19:10:30 +08:00
编译的时候都变成地址了吧
wangxn
2021-08-01 19:10:39 +08:00
变量名和实际地址的对应关系只有在编译时才是必要的。运行时直接操作地址就行。
chashao
2021-08-01 19:13:14 +08:00
编译的时候用到这个栈变量地址的地方都会变成栈指针偏移来表示吧
yezheyu
2021-08-01 19:15:48 +08:00
@wangxn 也就会说变量名只存在于代码中给程序员看的,编译后已经被替换成内存地址 0x002,内存中实际存在的是 0x002,而 a 根本就没存在过,这样理解对吗?
wangxn
2021-08-01 19:45:33 +08:00
@yezheyu 是的。可以这么理解。不过一般调试版本的可执行文件还是会附带这个对应关系用来调试,生产环境用的发布版本就不必要了。
akira
2021-08-01 20:04:37 +08:00
@yezheyu 编译型的语言,是的。 其实你只要去看一下对应的汇编语言,基本上就很清晰了
mainlong
2021-08-01 20:08:46 +08:00
程序运行需要环境,比如运行 python 就需要 python 解释器,那么解释器就会针对这段代码产生 temp 文件,里面就有变量 a 和地址 0x002 的映射。


我猜大概就是这个意思。肯定有编译器,解释器的参与。因为硬件不认识变量 a 。
hahasong
2021-08-01 21:15:04 +08:00
编译过程中会有个符号表
chenyu8674
2021-08-01 21:21:34 +08:00
建议看下《编译原理》,之前不懂的很多问题都能想明白

另外通过(尤其是中文环境下的)博客学习知识是效率很低的做法
Mohanson
2021-08-01 21:43:47 +08:00
事实上 a=10 这玩意大概率是放在指令的立即数里面的
littlewing
2021-08-01 22:54:54 +08:00
符号表
xiadong1994
2021-08-01 22:58:36 +08:00
如果是一段很小的代码,优化后 a 可能直接放寄存器,内存地址都没有
ipwx
2021-08-01 23:33:58 +08:00
+1 可能在寄存器里面
hefish
2021-08-01 23:41:23 +08:00
同学,你应该去看一门课程,叫编译原理
GeruzoniAnsasu
2021-08-01 23:52:01 +08:00
有一个“学编程”学不到的很重要的事实:

编译器并不「翻译你写的代码」,它实际上是「照着你的代码创造能产生一致结果的过程」。


在不同语言里,“声明 a=10”很可能会产生完全不一样的结果。
- C 系语言在未优化前可能会分配一块代表 a 的内存,内存的位置取决于 a 所在的作用域;
- 一些解释型语言比如 cpython 会创造一个存放 10 的对象,这会给对象本身开一块内存,然后在特定结构中放 10,甚至一个指向静态常量表里「 10 」的指针;
- 一些语言完全没有“变量”,只有“名字绑定”,所以大概会在特定符号表结构中插入「 a 」以及它的替换物「 10 」


所以#8

> 也就会说变量名只存在于代码中给程序员看的,编译后已经被替换成内存地址 0x002,内存中实际存在的是 0x002,而 a 根本就没存在过,这样理解对吗

仅仅是特定情况下(指 C 系语言中)可能(指没被优化掉,变量正常地参与了计算等等)是对的
msg7086
2021-08-02 04:48:39 +08:00
另外,编译器很可能会把你写的代码替换成等效的别的代码。比如你写一个循环,把输入的数字累加 100 次,编译器很可能把这个操作转写成乘法,编译的时候甚至可能编译成位移加法。经过重度优化后的程序可能已经跟你写的代码完全不同了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/793017

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX