我正在做一个小实验。
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
int A[5][5];
cout<<A[0]<<" "<<&A<<" "<<*A;
return 0;
}
它为所有情况打印相同的值。有人可以解释为什么会这样吗?
我正在做一个小实验。
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
int A[5][5];
cout<<A[0]<<" "<<&A<<" "<<*A;
return 0;
}
它为所有情况打印相同的值。有人可以解释为什么会这样吗?
首先要了解的是您要打印的内容:
cout<<A[0]<<" "<<&A<<" "<<*A;
表达式A[0]
是一个左值表达式,其类型int[5]
引用内部的第一个内部数组A
,是一个指向数组&A
的类型的右值表达式。finally等价于,即类型的左值表达式。int (*)[5][5]
A
*A
A[0]
int[5]
语言中没有定义(您也不能提供它们)将转储 aint[5]
或 a的运算符int (*)[5][5]
,因此编译器尝试找到它可以找到的最佳匹配,并发现存在一个打印 a 的运算符void*
。int[5]
可以衰减为int*
引用 的a A[0][0]
,并且 that 本身可以转换为 a void*
。int (*)[5][5]
是一个指针,因此可以转换为void*
,因此重载对这两种情况都有效。
该语言定义了数组在内存中的布局,特别是它要求数组和数组的第一个元素布局在相同的内存地址中,所以如果你要打印的地址,&A
它&A[0]
会打印相同的值,并且因为&A[0]
也位于其第一个元素的相同内存位置,所以&A[0][0]
也指相同的地址。
回到上面你正在打印的代码是:
cout<< static_cast<void*>(&A[0][0])
<< " " << static_cast<void*>(&A)
<< " " << static_cast<void*>(&A[0][0]);
遵循上面的推理,它必须具有相同的精确值,即使在第二种情况下类型不同。
A[0]
, &A
,*A
都是指向同一个内存位置的不同类型的指针。相同的值(某种),不同的类型。
Expression Symmetric Type
----------------------------------------------------------------------------
A address of first row. int[5][5]
&A[0][0] address of first element int*
&A address of 2d array int(*)[5][5]
*A = *( A + 0) = A[0] = address of first element int[5] = decays to int*
in a expression
我的 5*4 维字符数组示例:
A
+---201---202---203---204---206--+
201 | +-----+-----+-----+-----+-----+|
A[0] = *(A + 0)--►| 'f' | 'o' | 'r' | 'g' | 's' ||
207 | +-----+-----+-----+-----+-----+|
A[1] = *(A + 1)--►| 'd' | 'o' | '\0'| '\0'| '\0'||
213 | +-----+-----+-----+-----+-----+|
A[2] = *(A + 2)--►| 'n' | 'o' | 't' | '\0'| '\0'||
219 | +-----+-----+-----+-----+-----+|
A[3] = *(A + 3)--►| 'd' | 'i' | 'e' | '\0'| '\0'||
| +-----+-----+-----+-----+-----+|
+--------------------------------+
关于图形示例的简要说明。
- 图中
A
表示从地址 201 开始的完整二维数组,并且&A
给出完整二维数组的地址 = 201*A = *(A + 0)
=A[0]
指向第一行 = 201- 注意值
A[0][0]
在'f'
我的示例中,并&A[0][0]
给出[0][0]
元素的地址 = 201- 注意
&A[0][0]
与 相同*A
,因为&A[0][0]
=>&(*(*A))
=>&**A
=>*A
所以所有A[0]
, &A
, *A
,A
都是相同的,但对称地不同。
A[0]
观察, &A
, *A
,之间的差异A
。键入以打印sizeof()
信息。例如
cout<<sizeof(A[0]) <<" "<<sizeof(&A) <<" "<<sizeof(*A) <<" "<< sizeof(A);
第二次尝试使用以下方法打印下一个位置地址:
cout<<(A[0] + 1)<<" "<<(&A + 1) <<" "<<(*A + 1)<<" "<<(A + 1);
如需更详细的解释,请务必阅读此答案。
A[0] 这等价于 *(A + 0),或更简单地说是 *A。
&A 有点棘手。A 是 int[5][5] 类型,由堆栈上 100 字节的连续区域表示。A 的地址是该区域的开始 - 它等于指向第一个元素的指针。第一个元素地址也是*A的存储位置。
数组,在最基本的层面上,是指向内存中某个点的指针。数组中的其他元素连续存储在该元素之后,并且索引告诉计算机从第一个元素跳转到所需的位置的位置。A[0]
正在打印第一行中第一个元素的地址,&A
正在打印 A 所在的地址,即第一行的第一个元素所在的地址,并且*A
与 相同A[0]
。