当存储非指针值时,C 中实际发生了啥? [复制]
Posted
技术标签:
【中文标题】当存储非指针值时,C 中实际发生了啥? [复制]【英文标题】:What is actually going on in C when a non-pointer value is stored? [duplicate]当存储非指针值时,C 中实际发生了什么? [复制] 【发布时间】:2018-08-12 16:34:47 【问题描述】:重要提示:这试图一次问太多事情并且具有误导性,因为我是在对如何使用指针的错误假设下编写的,它最终看起来就像是重复的。请改为查看:How are variables tied to their values in C?
假设在地址0001
处有一个值4
,然后我们将地址0001
赋给变量num
。我们可以将其可视化为两个表:
VARIABLE|ADDRESS ADDRESS|VALUE
num |0001 0001 |4
据我了解,这将是以下代码的最终产品:
int temp = 4;
int * num = &temp;
但是,第一行 int temp = 4;
发生了什么?第一行会产生这样的结果吗?
VARIABLE|ADDRESS ADDRESS|VALUE
| temp |4
指向指针的指针是如何工作的?请问代码:
int temp = 4;
int * num = &temp;
int ** pnum = #
生产这个?
VARIABLE|ADDRESS ADDRESS|VALUE
num |0001 0001 |4
pnum |0002 0002 |0001
什么是正确的思考方式?引擎盖下到底发生了什么?另外,当存储结构而不是数字时,这会如何变化?
我了解以上示例可能完全不正确;他们只是将我的问题置于上下文中。
【问题讨论】:
原始值存储在堆栈中,因此您提到的第一行将值 4 存储在堆栈中,相对于封装值声明的函数(请参阅此处有关堆栈内存使用的更多信息:@ 987654322@) “正确的思考方式是什么?”对我来说,我觉得这很好:temp
的地址在“int street”上,门牌号是“123”。 temp
的值为 4。num
的地址位于“int * street”上,门牌号为“456”。 num
的值为“int street:123”。 “int street”和“int * street”可能指的是同一个“street”,也可能不是。不确定这种抽象是否适合学习者。幕后实际发生的事情取决于编译器和处理器——没有一个答案——太宽泛了。
还会有一个表(在编译时)说名称temp
指的是地址0001
123421重复的先前问题怎么样,它们与您的问题有什么关系?
无论如何,您的表格在概念上都非常错误。指针有一个地址和一个值。分配给指针的值是一个地址,但它不是指针本身的地址。
【参考方案1】:
并不是所有的变量都需要在内存系统中有一个地址,一些变量的生命周期很短,以至于它们可以在寄存器中度过它们的整个生命周期。在这种情况下,编译器会将它们分配(重命名)为eax
、ebx
或r1
、r2
。寄存器是 CPU 中可以保存可变内容的插槽。
因为许多架构的寄存器数量有限(x86-64 中的 8 个虚拟(机器语言可见)寄存器,IA64 中的 256 个寄存器......)其余变量被分配(编译)到内存中的地址,它将始终在堆栈上。堆栈(由esp
寄存器跟踪,一个特殊的寄存器)是一个后进先出分配器,支持操作系统(内存页面随着它的增长而活跃),因此编译器只需要获取当前的堆栈指针并递增它根据要分配的变量的大小,这就是变量的地址。
与您演示的第一种情况一样,赋值是通过发出带有硬编码值的mov
汇编命令来完成的,因此该常量存在于程序的内存空间中。这意味着值来自指令本身。 (L1:inst cache->fetcher->CPU pipeline->mov->STORE pipeline->L1:data cache)
其余的就像你感觉到的那样工作。
【讨论】:
您在 x64 中忘记了 r8-r15。 @liliscent 确实如此。让我们将此链接作为 x64 寄存器的参考en.wikibooks.org/wiki/X86_Assembly/…以上是关于当存储非指针值时,C 中实际发生了啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章