当p
是指向数组的指针时,为什么:
*p == p == &*p
简单的程序,仅是c ++中的二维数组:
int p[][3] = {{1,2,3}};
cout << p << " " << *p << " " << &*p;
结果:0x22fe20 0x22fe20 0x22fe20
答案 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
的列是第一个子数组的第一个元素。
您可能会注意到,X
,Y
和Z
都从标有*
的相同地址开始。这是数组的地址,第一个子数组的地址和第一个子数组的第一个元素的地址。
答案 2 :(得分:0)
p
是指向数组开头的指针。
*p
是指向该数组中第一个数组(也称为数组的开头)的指针
&*p
与p
是同一件事。
答案 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 *
),值相等。