变量及其引用如何在计算机内存中存储和访问?

ace*_*ber 5 memory variables programming-languages language-concepts

变量如何存储在计算机内存中?

例如:当我们指定

整数x = 15;

通常,计算机在其 RAM 中分配 4 字节的内存块,在分配的 4 字节中以 0 和 1 的形式存储值 15,x 指分配的 4 字节内存的地址。

现在,我的疑问是 x 如何指代内存位置。参考存储在哪里以及如何存储?

当我们使用 x 时,它如何知道引用该内存位置。

对于 java 和 python 等不同语言来说,这是否有所不同?

对于不同的数据类型这有不同吗?

如果您能制作视频或博客来澄清这一点,我将很高兴。

lin*_*fan 7

通常,计算机在其 RAM 中分配 4 个字节...

整个句子完全正确。只是,有不同类型的分配。最简单的是,计算机在某一时刻拥有一定量的空闲且连续的内存。当程序启动时,所有(空闲且连续的)内存都会分配给新程序。程序完全负责管理内存,并且不在该内存区域之外进行写入。这就是 DOS(实模式)的工作原理 - 非常简单。程序(好吧,它的运行时)仅被告知内存区域的起始和结束地址。它将一些“基址”寄存器“映射”到该 RAM 中,例如,地址 0 指的是起始地址,程序可能知道变量 X 所在的位置。更先进的操作系统不仅如此,例如具有阻止程序尝试在其允许的内存之外读取或写入的机制。甚至更复杂的操作系统可以最初为程序提供一些内存,然后在程序需要时提供更多内存。

现在,我的疑问是 x 如何指代内存位置。参考存储在哪里以及如何存储?

通常,引用根本不存储在(编译的)程序中。你(程序员)所说的“X”,对于程序来说只是一个地址。第一个变量地址 0,第二个变量地址 4,依此类推。调试符号在未剥离时会跟踪赋予地址的“高级”名称;但它们由调试器使用,并且在技术上不是“程序”的一部分。

当我们使用 x 时,它如何知道引用该内存位置。

我们来写一个简单的C程序:

int x = 15;
int y = 20;
int s;

s = x+y;
Run Code Online (Sandbox Code Playgroud)

编译器看到“int x”并将地址0分配给x。然后看到“int y”并将其分配给地址4。然后将地址8分配给“s”。当然,这些地址在整个编译过程中都会被记住。同时它看到“x=15”和“y=20”,因此输出这些指令:

"store an integer of 4 bytes, value 15, at address 0"  
"store an integer ..., 20, at address 4"
Run Code Online (Sandbox Code Playgroud)

最后它看到“s=x+y”并输出:

"take in the left hand the int (4 bytes) value at address 0"
"take in the right hand the int value at address 4"
"pour the left hand in the right hand"
"pour the right hand in 4 bytes at address 8"
Run Code Online (Sandbox Code Playgroud)

如您所见,不再有 xy 或 s,只有地址(这是一个非常简化的解释)。

对于 java 和 python 等不同语言来说,这是否有所不同?

是的,但不要太多。变量的名称始终引用地址。纯解释型语言必须记住名称,因为编译和执行之间没有分离,而像java这样的中途语言(我说中途是因为java既是编译器又是解释器)可以做更复杂的事情。

对于不同的数据类型,这是否有所不同?

对于简单类型,不需要。在C语言中,如果我们不考虑指针和堆,所有的变量都被同等对待,只是它们的长度发生了变化。int 可以是 4 个字节长,char 可以是一个字节,数组的长度由程序员指定,但变量始终引用包含该值的缓冲区的第一个位置。编译器为每个变量保留其地址、类型、长度,因此当它遇到源中的变量名称时,它可以知道要做什么(编译哪些指令)。


编辑“你能告诉我在编译过程中计算机中“x变成0”部分是如何发生的吗”

它的概念非常简单。编译器读取源文本。每次遇到变量声明时,它都会为其分配第一个空闲地址,然后将其增加变量的大小。开始时,该地址为 0。编译器读取“int x;”后,x 的地址变为 0,并且“当前”地址递增(对于 int,可能为 4 或 8)。变量名称、类型和地址被保留,并形成一个查找表。该表用于检查您是否没有两次声明标识符,并用于了解当源引用已声明的变量时在哪里读取和写入。如果源引用未声明的变量,编译器会抱怨,因为它在查找表中找不到该变量。注意:您发布了一个讨论指针的视频链接;指针也是变量,但它们引入了其他概念。我所说的关于地址的内容也适用于指针,从某种意义上说,它们只是变量,但它们的值的使用方式不同 - 我不明白你为什么坚持使用它们。