【问题标题】:How pointers in C/C++ actually store addresses?C/C++ 中的指针实际上是如何存储地址的?
【发布时间】:2020-11-08 03:06:59
【问题描述】:

如果int 以 4 个字节存储在内存中,如果每个字节具有唯一地址,那么这四个地址中的哪个地址会指向该 int 存储?

【问题讨论】:

  • 请以tour 开头并阅读How to Ask。此外,请阅读您应用的标签的描述。关于您的问题的进一步阅读:“endianess”。
  • 如果您想要理论方法,请阅读denotational semantics;如果您想要一种实用的方法,请研究您的 C 或 C++ 编译器的instruction set architecture(例如x86-64...),并要求您的编译器显示汇编代码:使用GCC,使用gcc -fverbose-asm -S -O 编译跨度>
  • 地址是无符号值 - 32 位或 64 位,取决于 CPU。在某些情况下,它可以是 16 位。指针是位于内存某处的变量。

标签: c++ c pointers memory memory-address


【解决方案1】:

指向intint*)的指针存储整数第一个字节的地址。 int 的大小对于编译器来说是已知的,所以它只需要知道它从哪里开始。 int 的字节如何解释取决于您机器的字节序,但这不会改变指针仅存储起始地址的事实(编译器也知道字节序)。

【讨论】:

  • 最好提到字节顺序以及它如何改变第一个字节的解释。
  • @aep 第一个字节是第一个字节,不管字节序。
  • @P__J__ 技术上是正确的。从那以后我一直在评论它,提到它可能会增强答案。字节序将决定如何解释 int 而不是第一个字节。
  • @eap 从 C 的角度来看,除非你双关语类型的字节序无关紧要。如果p 是引用int 的指针,则*p 将始终具有正确的值。 IMO 字节序与 OP 问题无关
【解决方案2】:

这 4 个 int 字节不存储在随机位置 - 它们是连续的。所以存储对象的第一个字节的引用(地址)就足够了。

【讨论】:

    【解决方案3】:

    取决于架构。在大端架构(M68K,IBM z 系列)上,它通常是最高有效字节的地址。在 little-endian 架构 (x86) 上,它通常是最低有效字节的地址:

     A   A+1 A+2 A+3    big-endian
    +–––+–––+–––+–––+
    |msb|   |   |lsb|
    +–––+–––+–––+–––+
     A+3 A+2 A+1 A      little-endian
    

    我可能会忽略其他奇怪的寻址方案。

    但基本上它是底层架构认为单词的“第一个”字节。

    【讨论】:

    • 你的插图有点混乱。该地址是具有最低地址的字节的地址,与目标系统中的当前字节序无关。
    • 取决于架构不,恐怕不是。
    • 这取决于@chqrlie,您是在谈论 C 抽象机器模型意义上的地址还是硬件意义上的地址。这些不需要一致。事实上,它们可能不重合是该标准对指针和指针操作语义的定义非常迟钝的原因。此外,它还取决于一个如何表示整数的“第一个”字节——在至少两种可能的位值意义上,或者在某种寻址模型或其他意义上。
    • @RobertSsupportsMonicaCellio:实际上并不像增加指向int 的指针使其指向int 数组中的下一个int。在一个假设的 CPU 上,int * 包含 last 字节的地址(即:具有最大地址的那个),将此指针转换为 (unsigned char*) 将不得不更改其值以产生unsigned char * 指向地址最低的字节。
    • @chqrlie 是的,将对象与字节混淆。我的错。已经删除了我的评论。谢谢。
    【解决方案4】:

    如果int 以 4 个字节存储在内存中,每个字节都有一个唯一的地址,那么这四个地址中的哪个地址是指向 int 的指针存储?

    指向int的指针通常存储int对象的第一个字节(存储在最低内存地址)的地址值。

    因此,int 的大小在特定的实现/架构中是已知的并且是恒定的,并且int 对象始终存储在连续字节中(其中两个之间没有字节),很明显以下内容((if sizeof(int) == 4) 三) 个字节属于同一个int 对象。

    int 对象的字节如何解释取决于字节序*。

    第一个字节通常根据特定架构自动对齐数据字大小的倍数,以便 CPU 可以最有效地工作。

    例如在 32 位架构中,当数据字大小为 4 时,第一个字节位于 4 字节边界 - 一个具有 4 倍数的地址位置。

    顺便说一句,sizeof(int) 并不总是4(虽然很常见)。


    *字节序会影响对象的解释是从(第一个)还是最少(最后一个)有效字节。

    【讨论】:

      【解决方案5】:

      C 标准没有指定如何在指针中表示地址。然而在大多数当前架构中,指向int 的指针将其地址存储为用于存储它的内存的第一个字节的进程内存空间中的偏移量,更准确地说是具有最低地址的字节。

      但请注意以下备注:

      • int 可能多于或少于 32 位。唯一的限制是它必须至少有 15 个值位和一个符号位。
      • 字节可能超过 8 位。大多数当前架构使用 8 位字节,但早期的 Unix 系统使用 9 位字节,一些 DSP 系统使用 16、24 甚至 32 位字节。
      • int 使用多个字节存储时,未指定如何在这些字节之间拆分其位。许多系统使用 little-endian 表示,其中最低有效位在第一个字节中,其他系统使用 big-endian 表示,其中最高有效位和符号位在第一个字节中。其他表示是可能的,但只是理论上的。
      • 许多系统要求int 的地址与其大小的倍数对齐。
      • 指针在内存中的存储方式也是系统特定的和未指定的。地址不一定代表内存中的偏移量,真实的虚拟的。例如,x86 CPU 上的 64 位指针有许多可以忽略的位,或者可能包含由 CPU 动态验证的加密签名。向指针的存储值加 1 不一定会产生有效的指针。

      【讨论】:

        猜你喜欢
        • 2017-11-08
        • 1970-01-01
        • 2010-12-08
        • 2020-05-25
        • 2021-11-28
        • 1970-01-01
        • 2011-04-25
        • 1970-01-01
        相关资源
        最近更新 更多