当p是二维数组时,为什么p,* p和&* p具有相同的值?

时间:2019-07-05 15:32:02

标签: c++ arrays pointers

p是指向数组的指针时,为什么:

*p == p == &*p

简单的程序,仅是c ++中的二维数组:

int p[][3] = {{1,2,3}};
cout << p << " " << *p << " " << &*p;
  

结果:0x22fe20 0x22fe20 0x22fe20

4 个答案:

答案 0 :(得分:3)

打印时,数组p会衰减为指向其第一个元素的指针。与&p相同。至于&*p,这就是被取消引用的p指向的地址。还是第一个元素-与前两个相同。

尽管类型不同。即使地址相同。 p是一个数组,但是&p是指向int数组的指针。

答案 1 :(得分:1)

使用数组的值时(在这种情况下为p),它将隐式转换为指向第一个元素的指针(与&p[0]相同)。这种转换称为衰减。

此外,数组的第一个元素与数组位于相同的地址。

  • p衰减为&p[0]。这是p的第一个元素的地址,它与数组p本身的地址相同。
  • *p在这里,p首先衰减到&p[0],因此完整表达式等效于*&p[0]*&互相抵消(根据C语言的定义; C ++使用不同的措词,但效果相同)。因此,它是p[0]的左值,即数组的第一个元素。在这种情况下,该元素是另一个数组,因此其值衰减为指向第一个元素(即&p[0][0])的指针。由于第一个元素的地址与数组的地址相同,因此p[0][0]的地址与p[0]的地址相同,该地址也与p的地址相同。
  • &*p和以前一样,&*互相抵消,结果与只使用p相同。

在内存中,一个4x4 2D数组看起来像这样:

  *
..0000111122223333..
  XXXXXXXXXXXXXXXX
  YYYY
  Z

在此图中,每一列代表一个内存位置。标记为X的列是2D数组的存储位置。

每个标记为0的列都是第一个子数组的元素,每个标记为1的列都是第二个子数组的元素,依此类推。

标记为Y的列是第一个子数组的存储位置。

标记为Z的列是第一个子数组的第一个元素。

您可能会注意到,XYZ都从标有*的相同地址开始。这是数组的地址,第一个子数组的地址和第一个子数组的第一个元素的地址。

答案 2 :(得分:0)

p是指向数组开头的指针。

*p是指向该数组中第一个数组(也称为数组的开头)的指针

从语法上讲,

&*pp是同一件事。

答案 3 :(得分:0)

如果您声明了这样的数组

int a [] = {1,2,3};

然后在表达式中使用(极少数例外,例如,运算符sizeof的操作数),将数组指示符隐式转换为指向其第一个元素的指针。所以在这句话中

std::cout << a;

相同
std::cout << &a[0];

或与

相同
std::cout << &*a;

在您的示例中,*p是一个数组{1,2,3},代表数组p的第一个元素。

用作语句中的表达式

std::cout << *p;

它转换为它的第一个元素的地址,即它等于第一个元素的地址。

所有这些地址都指向分配给数组的扩展区的开始。因此,尽管表达式p和表达式*p的类型不同(第一个表达式的类型为int ( * )[3],第二个表达式的类型为int *),值相等。