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

Why p, *p, &*p have the same value when p is a two dimension array?

本文关键字:二维数组 为什么      更新时间:2023-10-16

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

*p == p == &*p

简单程序,只是C 中的二维数组:

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

结果:0x22Fe20 0x22Fe20 0x22Fe20

阵列p在打印时腐烂到指向其第一个元素的指针。这与&p相同。至于&*p,这是 p指向的任何指数的地址。这再次是第一个元素 - 与前两个相同。

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

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

另外,数组的第一个元素位于数组所在的同一地址。

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

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

  *
..0000111122223333..
  XXXXXXXXXXXXXXXX
  YYYY
  Z

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

标记为0的每列是第一个子阵列的一个元素,每个列是第二个子阵列的元素等。

Y标记的列是存储第一个子阵列的位置。

Z标记的列是第一个子阵列的第一个元素。

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

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

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

&*pp是同一件事。

如果您声明了一个数组,例如这样

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

然后在表达式中使用(如罕见例外,例如操作员大小的操作数(,该数组指定器被隐式转换为指针转换为其第一个元素。所以在这个语句中

std::cout << a;

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

或与

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

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

用作语句中的表达

std::cout << *p;

它被转换为其第一个元素的地址,它是第一个元素的地址等于1。

所有这些地址都指向分配给数组的程度的开始。因此,尽管例如表达式p和表达式*p的类型是不同的(第一个表达式具有int ( * )[3]类型,而第二个表达式具有类型int *(,但它们的值仍然相等。