【问题标题】:Memory addresses, pointers, variables, values - what goes on behind the scenes内存地址、指针、变量、值——幕后发生的事情
【发布时间】:2013-06-21 06:42:33
【问题描述】:

这将是一个非常重要的问题,但自从我开始学习指针以来,我一直很好奇程序运行时幕后会发生什么。

据我所知,计算机内存通常被认为是一条长长的内存条,平均分为单个字节。当然,像下面这样的图片唤起了这样一个比喻:

我一直想知道的一件事是,内存地址本身代表什么?我确信内存地址显示为 8 位十六进制值(例如/00EB5748)并非巧合。这是为什么呢?

此外,当我声明一个变量 x 时,内存级别发生了什么?编译器是否只是为数据存储保留一个随机地址(+变量类型需要多少个连续地址)?

现在假设 x 是一个占用 2 个字节内存的无符号整数(即,值范围从 0 到 65536)。当我声明 x = 12 时,发生了什么?我等于 12 是什么?当我绘制概念图时,我通常有一个地址框(比如 &x),它指向一个看起来什么都不占的变量(x),我确信这不能完全准确地描述正在发生的事情。

在二进制级别发生了什么?地址 00EB5748 是否被视为 111010110101011101001000 并在某处存储值 12 或 1100?

我的困惑和好奇主要源于内存地址和声明的实际值之间的关系(例如/12、'a'、-355.2)。再举一个例子,假设我们的地址 00EB5748 指向一个字符 's',根据 ASCII 图表其值为 115。该地址是否通过在内存中的该位置翻转适当的 1 和 0 来描述将值 115 存储在 1 个字节中的位置?

【问题讨论】:

    标签: variables pointers memory-address


    【解决方案1】:

    只要打开任何一本书。您将看到页面。每页都有一个编号。连续的页面由连续的数字编号。您对编号页面有任何困惑吗?我想不是。那么你不应该与计算机内存混淆。 在计算机时代之前,书籍是主要的记忆存储设备。计算机内存的基本概念来源于书籍:书有页-> 计算机内存有存储单元,书有页码-> 计算机内存有内存地址。

    • 我一直在想一件事,内存地址本身代表什么?

    数字。每个记忆单元都有编号,就像书中的每一页一样。

    • 此外,当我声明一个变量 x 时,内存级别发生了什么?编译器是否只是为数据存储保留一个随机地址(+变量类型需要多少个连续地址)?

    内存管理器标记一些被占用的内存单元并将第一个保留单元的地址告诉编译器。编译器将变量的名称和类型与此地址相关联。 (这张图来自我的脑海,可能不准确)。

    • 当我声明 x = 12 时,发生了什么?

    当您声明变量x 时,为该变量保留了内存单元。现在您将12 写入这些存储单元。请注意,12 以某种方式进行了二进制编码,具体取决于变量x 的类型。如果x 是 unsigned int 占用 2 个内存单元,那么一个单元将包含 0,另一个将包含 12。因为 12 的二进制整数表示是

    0000 0000 0000 1100
    |_______| |_______|
      cell      cell  
    

    如果 12 是浮点数,它将以其他方式编码。

    【讨论】:

    • 喜欢计算机内存和书籍之间的类比。现在对我来说很有意义!
    【解决方案2】:
    1. 内存地址只是给定字节在内存中的位置。第零个字节位于 0x00000000。第十个在 0x0000000A。第 65535 个在 0x0000FFFF。等等。
    2. 局部变量位于stack* 上。编译代码块时,编译器会计算保存所有局部变量所需的字节数,然后递增堆栈指针,以便所有变量都可以放在它下面(以及其他一些东西,如帧指针和返回地址和什么的)。然后它只记住,例如,局部变量 x 位于堆栈指针的偏移量 -2 处,foo 位于偏移量 -4 处,依此类推,并在以下代码中引用这些变量时使用这些地址。李>
    3. 由于编译器知道 x 位于地址(堆栈指针 - 2)处,因此当您执行 x = 12 时,该位置设置为值 12。
    4. 不完全确定我是否理解这个问题,但说您想读取地址 0x00EB5748 处的内存。 CPU 中的控制单元读取指令,发现它是加载指令,并将地址(当然是二进制)传递给加载/存储单元,以及其他一些垃圾,例如要读取多少字节。然后 LSU 将该地址发送到某个内存(可能是 L1 缓存),并在一定时间后返回值 12。然后,这些数据可用于,例如,放入寄存器,或发送到 ALU 进行算术运算,或其他任何事情。
    5. 这似乎是准确的,是的。回到第一个问题,地址只是表示“内存中的字节数 0xWHATEVER”。

    希望这至少能澄清一点。

    *我也应该解释一下堆栈。堆栈是为局部变量(和其他一些东西)保留的一部分内存。它从内存中的一个固定位置开始,并在一个称为堆栈指针的特殊寄存器中包含的内存地址停止。首先,堆栈是空的,因此堆栈指针只包含堆栈的开头。当您将更多数据放入堆栈时,SP 会增加。这意味着您可以随时将更多数据放在它上面,只需将其放在 SP 中的地址处,然后递增 SP,以便再次超出该地址的任何内容都是空闲内存。

    【讨论】:

    • 另外,如果有人发现任何事实错误,请更正。我的资料来源包括几年前我半睡半醒的讲座、我可能在书中读到的东西或任何不知道的东西、梦想、幻觉等等。
    猜你喜欢
    • 2019-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 2020-12-30
    • 1970-01-01
    • 1970-01-01
    • 2013-12-22
    相关资源
    最近更新 更多