【问题标题】:Why are `&array` and `array` pointing to the same address?为什么`&array`和`array`指向同一个地址?
【发布时间】:2019-07-15 08:59:29
【问题描述】:

直到现在,我还认为数组和指针是一样的。但我发现了一个奇怪的案例:

代码

int array[5] = { 10,11,12,13,14};

std::cout << array << std::endl;
std::cout << &array << std::endl;
std::cout << &array[0] << std::endl;

int *pArray = new int[5];

std::cout << pArray << std::endl;
std::cout << &pArray << std::endl;
std::cout << &pArray[0] << std::endl;

输出

0x7ffeed730ad0
0x7ffeed730ad0
0x7ffeed730ad0

0x7f906d400340
0x7ffeed730a30
0x7f906d400340

如您所见,array&amp;array 具有相同的值。但是pArray&amp;pArray 具有不同的价值。如果数组与指针相同,则数组的地址应该与数组不同。 array&amp;array 怎么会一样呢?如果array&amp;array 相同,那么保存数组值的内存地址是什么?

【问题讨论】:

  • 这是因为数组不是指针。在数组的情况下,&amp;aa 是一回事。在指针的情况下,p 是指针指向的地址,&amp;p 是存储指针值的地址。
  • 这里我们可以见证语言的不一致。 new int[5] 应该返回指向 int[5] 的指针,而不是指向 int 的指针。
  • @geza 这有什么不同?指针就是指针
  • @geza 这将需要添加(丑陋的)可变长度类型,或者创建动态数组的替代方法。

标签: c++ arrays pointers


【解决方案1】:

普通的array 衰减为指向其第一个元素的指针,它等于&amp;array[0]。第一个元素也恰好从与数组本身相同的地址开始。因此&amp;array == &amp;array[0]

但需要注意的是,类型是不同的:

  • &amp;array[0] 的类型是(在您的示例中)int*
  • &amp;array 的类型是int(*)[5]

&amp;array[0]&amp;array 之间的关系可能会更容易“以图形方式”显示(添加了指针):

+----------+----------+----------+---------+----- -----+ |数组[0] |数组[1] |数组[2] |数组[3] |数组[4] | +----------+----------+----------+---------+----- -----+ ^ | &数组[0] | &大批

作为额外的补充,array 衰减为指向其第一个元素的指针,即 array 衰减为 &amp;array[0],因此将具有相同的类型。


但指针的情况有所不同。指针pArray 指向某个内存,pArray 的值就是那个内存的位置。这就是您使用pArray 时得到的结果。也和&amp;pArray[0]一样。

当你使用&amp;pArray 时,你会得到一个指向指针的指针。也就是说,您获得了变量pArray 本身的位置(地址)。它的类型是int**

指针pArray有点图形化,会是这样的

+--------+ +------------+------------+-----------+--- --------+------------+-----+ |数组 | ----> |数组[0] |数组[1] |数组[2] |数组[3] |数组[4] | ... | +--------+ +------------+------------+-----------+--- --------+------------+-----+ ^ ^ | | &pArray &pArray[0]

[注意“数组”末尾的...,这是因为指针不保留有关它指向的内存的信息。指针仅指向特定位置,即“数组”的“第一个”元素。将内存视为“数组”取决于程序员。]

【讨论】:

  • 不确定(void*)&amp;array 是否应该等于(void*)(&amp;array[0]) BTW。 (&amp;array[0]array 应该)。
  • @Jarod42 数组与数组的所有单个元素完全重叠。数组元素之前、之间或之后没有“填充”或“间隙”。
  • 我的意思是 int (&amp;)[N] 衰减到 int* 并因此导致相同的指针,int (*)[N]int* 是不相关的类型。我不认为它们必须是平等的(一旦转换为“common”void*),即使以这种方式实现它似乎更简单。
  • @Jarod42 我已经提到了不同的类型,但这并不重要。不幸的是,我没有引用 C++ 规范中的任何引号,但我清楚地记得其中有一些内容确实表明 (void*) &amp;array == (void*) &amp;array[0] 必须仍然是正确的(即使它必须从几个不同的部分一起混淆)。否则(*(&amp;array))[0] 之类的东西将不起作用。
  • *&amp;a 是“noop”(对于没有邪恶一元运算符 & 的类型),所以你的例子不是正确的:/ .
【解决方案2】:

X 数组的行为必须像指向内存中 X 的连续列表的指针,就像指针一样。但是,它没有写在存储数据的内存必须是它自己的地址和可写的地方。在显式指针的情况下,该地址(在这种情况下为堆栈)有一个新的分配,但是对于一个数组,在堆栈上,编译器已经知道内容在哪里,因此不需要新的分配。

因此,将其视为指针而不进行索引是不安全的。例如:

pArray = nullptr; // This is a memory leak, unless a copy is taken, but otherwise fine.
array = nullptr; // This is will make the compiler upset

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-25
    • 1970-01-01
    • 2017-11-02
    • 2015-08-14
    • 2022-01-02
    • 1970-01-01
    相关资源
    最近更新 更多