【问题标题】:What is the value of a pointer if it is pointing to an array or an object? [closed]如果指针指向数组或对象,它的值是多少? [关闭]
【发布时间】:2013-08-19 09:07:52
【问题描述】:

我知道我的问题可能非常基本,但我想知道在内存中获得多个单元格的对象,例如数组和用户定义的对象(需要在内存中拥有多个单元格,因此范围为内存中的连续地址),指针对这种对象的真正含义是什么?是 C++ 中的变量包含这些对象在内存中的地址吗(逻辑上不正确,因为这些对象在内存中占用了多个单元格,因此具有连续的地址范围),或者假设指向这些对象的指针只是开始这些对象的地址(更合理)。

请帮我理解;如果您不相信我对 C++ 指针定义的解释,请给我正确的解释。

在大多数 C++ 教程中,它说指针只包含内存中其他变量的地址。

【问题讨论】:

  • Difference between pointer and pointer variable 和许多其他的可能重复。
  • 是的,您的“更理性”的理解是正确的。我不知道为什么人们会否决一个简单的问题,其答案通常不会在面向初学者的基本 C++ 书籍中明确写出。
  • @Joni:我看不出这是链接问题的副本吗?这个问题是关于指向更大对象/数组的指针的行为,而另一个问题是关于指针的更基本的理解。
  • @Grizzly,我看到问题已被编辑并更清晰,我正在撤回我的近距离投票。

标签: c++ pointers


【解决方案1】:

假设您有一个变量 a 声明和初始化,如

int a = 5;

然后你创建一个指针并使用地址运算符& 使 int point 指向a

int* pointer_to_a = &a;

pointer_to_a 的实际值是a 在内存中的地址。但是编译器知道它是一个指针,所以你可以使用pointer_to_a 来访问a 的内容和解引用运算符*

*pointer_to_a = 10;
std::cout << "a = " << a << '\n';

上面将打印10,因为你设置了pointer_to_a指向10的内容。

【讨论】:

    【解决方案2】:

    如果我(作为编译器)知道int(在这个特定系统上) 4 字节长,那么指向int 的指针只需要告诉我“开始”在哪里int 是:我只需要读取它和接下来的 3 个字节!

    对于像数组这样的更大数据结构,情况也是如此:如果我知道我的数组从哪里开始,我就知道我可以通过将一个项目的大小添加到地址来访问每个后续元素。例如,如果我有一个从地址 100 开始的int a[],而一个int 是 4 个字节,那么

    a[32] = (address of a) + (32 * size of int) = 100 + 128 = 228 所以字节 228 到 231 是 a[32] 处的整数。

    使这个更容易使用的原因是编译器为我们抽象了不同大小的数据类型。如果我将整数指针加 1,地址实际上会增加 4!这是因为我很少(几乎从不)想要读取半个整数:我更可能希望依次查看一系列整数。

    【讨论】:

      【解决方案3】:

      来自here

      您计算机的内存可以想象为一系列内存 单元,每个单元都是计算机管理的最小大小(一个字节)。 这些单字节存储单元以连续方式编号,因此 因为,在任何内存块中,每个单元格的编号都与 前一加一。

      这样,每个单元格可以很容易地在内存中定位,因为它有 一个唯一的地址,所有的存储单元都遵循一个连续的模式。 例如,如果我们正在寻找单元格 1776,我们知道它正在运行 在单元格 1775 和 1777 之间,正好是一千个单元格 776 之后和 2776 之前正好一千个单元格。]1

      【讨论】:

      • 这是一个相当简单的观点,并不是 C++ 标准描述它的方式。特别是,没有假设存储单元形成连续(两个随机指针之间不支持指针运算),也没有假设每个单元都有一个唯一的地址(实际上在 8086 上它们没有) .
      【解决方案4】:

      这可能有助于想象操作系统的内存布局 Here

      当你指定一个指针时,你也指定了它将持有的类型指针,例如整数* 在这种情况下,编译器将保留 4 个字节(通常是 int 的大小)并以 little-endian/big-endian 格式存储值。

      我认为你是正确的,它只有一个指向起始单元格的指针,如果你说 p++,那么编译器将增加 4 个字节并指向其他地址。

      如果你想引用 p 指向的下一个单元格,那么认为你可能需要读取地址(HEX 地址)并递增和尊重它。

      【讨论】:

        【解决方案5】:

        对于数组,指针的含义与其他所有内容完全相同。

        一个指针正好指向一个对象的位置(作为对 unwind 指向数组指针的反对意见的回应:这个 一个对象 也可能是一个数组),不多不少。它不知道对象数组的大小(如果有,也不在乎)。1
        完全有可能创建一个指向单个值的指针并将其作为某个大小的数组访问,尽管这既不明确也不明智(它可能会崩溃)。也完全可以使用指向大小为 5 的数组的指针并访问第 10 个元素。同样,这没有任何意义并且可能会崩溃,但没有什么能阻止你这样做(除了编译时常量索引,至少一些编译器可能会发出警告)。指针不知道。

        对于一个结构,指针知道结构在内存中的位置,不多也不少。最重要的是,编译器知道其他细节,例如成员到这个基地址的偏移量。但是,此信息绑定到您用来取消引用指针的 type(而不是指针本身!)。
        因此,如果您让Banana 指向汽车(通过投射、意外或算术),通常可以通过Banana 指针访问Car 对象。当然,这没有任何意义,但这是可能的。指针不知道有什么区别,编译器会“当做”。


        1 是的,如果它是一个指向数组的指针,编译器就知道 那个 数组的大小。但这仅对类型正确性很重要。尝试将 5 数组分配给 4 数组指针时会出现编译错误,因为它们是不同的东西。但这与指针无关。 指针仍然不知道数组的大小,也不知道是一个数组还是一个数组数组。您仍然可以以任何一种方式使用它(可能会产生灾难性的影响),并且没有任何逻辑可以防止您造成伤害。

        【讨论】:

        • -1,编译器通常非常关心指向对象的大小(因此指针算法的工作方式就是这样)。
        • @unwind: 编译器关心 a) 类型,如果需要会给出编译错误,b) 关于 one 元素的大小,即指向的那个到。它不“关心”或执行其他任何事情。否则,您将如何能够越界访问数组?此外,分配器显然关心它分配的块的大小,但这与问题无关——指针不知道也不关心。
        • 当然,但是“一个元素”可能是,例如,一个数组。例如,请参阅this question's top answer。也见this brief example。您听起来好像指向数组的指针不存在,但也许我只是没有正确阅读您的答案。
        • @unwind:当然存在指向数组的指针,呵呵 :) 但是指针不知道,反正也不知道。在您链接的示例中,指向 8 整数数组的指针不知道它是否指向 one 8 整数数组(这只是“某种类型”的一个对象,并且除了编译器强制类型无关紧要),或者它是否可能指向一个由 8 个整数组成的数组的 5 个数组。而且,原则上,您可以合法地将其分配给一个普通的普通int*,它甚至不知道第一个数组。它只知道一个整数,即 8 数组对象中的第一个元素。
        • 我不明白“知道”是什么意思。当然,内存中的指针本身不包含有关它指向的类型的任何信息,但这并不意味着什么,因为它(例如)也不包含说明它是指针的信息。编译器都在与位关联的类型中。
        猜你喜欢
        • 1970-01-01
        • 2017-04-26
        • 1970-01-01
        • 2021-07-08
        • 1970-01-01
        • 2016-12-23
        • 2012-03-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多