当存储非指针值时,C中实际发生了什么?

What is actually going on in C when a non-pointer value is stored?

本问题已经有最佳答案,请猛点这里访问。

重要信息:这试图一次询问太多的事情,并且具有误导性,因为我在关于如何使用指针的错误假设下编写了它,并且最终看起来像一个重复项。请改为查看:变量如何与C中的值绑定?

让我们考虑在地址0001处有一个值4,然后将地址0001分配给变量num。我们可以将其可视化为两个表:

1
2
VARIABLE|ADDRESS    ADDRESS|VALUE
num     |0001       0001   |4

据我了解,这将是以下代码的最终产品:

1
2
int temp = 4;
int * num = &temp;

但是,第一行int temp = 4;是怎么回事?第一行会产生这样的结果吗?

1
2
VARIABLE|ADDRESS    ADDRESS|VALUE
        |           temp   |4

指针如何工作?代码是否会:

1
2
3
int temp = 4;
int * num = &temp;
int ** pnum = #

产生这个?

1
2
3
VARIABLE|ADDRESS    ADDRESS|VALUE
num     |0001       0001   |4
pnum    |0002       0002   |0001

对此有什么正确的想法?实际情况到底是怎么回事?另外,当存储结构而不是数字时,这会如何变化?

我了解上述示例可能完全不正确;他们只是将我的问题具体化。


并非所有变量都需要在内存系统中有一个地址,有些变量寿命很短,因此可以在寄存器中保留整个寿命。在这种情况下,它们会由编译器分配(重命名)为eaxebxr1r2之类的东西。寄存器是CPU中可以容纳变量内容的插槽。

由于许多架构的寄存器数量有限(x86-64中有8个虚拟(对机器语言可见)寄存器,IA64中有256个寄存器...),其余变量将分配(编译)到内??存中的地址,这将总是在堆栈上。堆栈(由esp寄存器(一个特殊的寄存器跟踪))是一个后进先出的分配器,具有操作系统的支持(随着内存页面的增长,内存页面会不断增长),因此编译器只需采用当前的堆栈指针并对其进行递增由要分配的变量的大小决定,这就是变量的地址。

就像您在第一种情况中所展示的那样,值的分配是通过发出带有硬编码值的mov汇编命令来完成的,因此常量存在于程序的存储空间中。这意味着该值来自指令本身。 (L1:inst缓存->提取程序-> CPU管道-> mov-> STORE管道-> L1:数据缓存)

其余的工作就像您感觉到的那样。