int a[3][3]={5};
printf("&a = %u \n a = %u \n*a = %u\n&a[0][0]=%d\na[0][0]", &a, a, *a, &a[0][0], a[0][0]);
输出: -
&a = 2359028
a = 2359028
*a = 2359028
&a[0][0]=2359028
a[0][0] =5
这些怎么可能都一样?
如果a = 2359028的值,则*a
不应在地址2359028处给出值,即5?
答案 0 :(得分:5)
&a
为您提供数组的地址。它的类型为int (*)[3][3]
。容易。
a
表示数组本身,将进行数组到指针的转换,成为指向数组第一个元素的指针。数组的第一个元素是类型为int[3]
的子数组,因此我们得到一个指向该子数组的指针。该指针的类型为int (*)[3]
。它具有与以前相同的地址,因为第一个子数组位于数组的开头。
使用*a
,数组再次进行数组到指针的转换,以获得与之前一样的指向子数组的指针。然后取消引用以获得子阵列本身。然后,表示子阵列的表达式也经历了数组到指针的转换,为您提供了指向其第一个元素的指针。第一个元素的类型为int
,因此指针的类型为int*
。第一个元素的地址与它所属的子数组的地址相同,正如我们所见,它与整个数组的地址相同。
&a[0][0]
首先获取第一个子数组的第一个元素,然后获取它的地址。这为您提供了与前一点完全相同的指针。
因此,所有这些指针都具有相同的值。
图解地:
0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ int │ int │ int │ int │ int │ int │ int │ int │ int │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
└─────────────────────────────────────────────────────┘
&a points at the entire array
└─────────────────┘
a gives you a pointer to the first subarray
└─────┘
*a gives you a pointer to the element 0,0
and so does &a[0][0]
这些区域都从相同的地址开始,因此指针具有相同的值。
答案 1 :(得分:0)
在C中,当一个数组涉及表达式时(例如,当传递给函数或指针算术时),它被隐式转换为指针。由于您将a
传递给printf
,因此会将其隐式转换为指向a
的指针,该指针与&a
相同。
您可能会对*a
看起来像是相对于&a
的双重引用这一事实感到困惑,后者返回了数组的地址,因此*a
应该通过此逻辑结果值a[0][0]
。但事实并非如此。
答案 2 :(得分:0)
“......不应该*在地址2359028给出值,即5?”
是和否。 *a
确实应该在地址a
为您提供对象。但是,在您的情况下,a
的类型为int[3][3]
。这意味着在这个间接级别,地址a
中的对象(如果我们将a
解释为指针)不是5
,因为您错误地认为,它实际上是整个1D数组{ {1}}。 a[0]
的类型为*a
,int [3]
中存储的值也是整个1D子阵列*a
。
因此,当您尝试a[0]
printf
时,实际上是将整个*a
子阵列指定为参数。该子阵列衰减到指针,指针自然指向同一位置(因为整个数组a[0]
及其第一个子阵列a
在内存中具有相同的位置)。这就是为什么打印a[0]
和a
作为指针(以及*a
)会导致打印相同的数值。
如果您希望在这种情况下访问&a
,则必须执行5
。仅仅**a
还不够。