c / c ++:二维数组变量下标

时间:2013-05-09 15:27:17

标签: c++ c

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?

3 个答案:

答案 0 :(得分:5)

  1. &a为您提供数组的地址。它的类型为int (*)[3][3]。容易。

  2. a表示数组本身,将进行数组到指针的转换,成为指向数组第一个元素的指针。数组的第一个元素是类型为int[3]的子数组,因此我们得到一个指向该子数组的指针。该指针的类型为int (*)[3]。它具有与以前相同的地址,因为第一个子数组位于数组的开头。

  3. 使用*a,数组再次进行数组到指针的转换,以获得与之前一样的指向子数组的指针。然后取消引用以获得子阵列本身。然后,表示子阵列的表达式也经历了数组到指针的转换,为您提供了指向第一个元素的指针。第一个元素的类型为int,因此指针的类型为int*。第一个元素的地址与它所属的子数组的地址相同,正如我们所见,它与整个数组的地址相同。

  4. &a[0][0]首先获取第一个子数组的第一个元素,然后获取它的地址。这为您提供了与前一点完全相同的指针。

  5. 因此,所有这些指针都具有相同的值。

    图解地:

      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]的类型为*aint [3]中存储的值也是整个1D子阵列*a

因此,当您尝试a[0] printf时,实际上是将整个*a子阵列指定为参数。该子阵列衰减到指针,指针自然指向同一位置(因为整个数组a[0]及其第一个子阵列a在内存中具有相同的位置)。这就是为什么打印a[0]a作为指针(以及*a)会导致打印相同的数值。

如果您希望在这种情况下访问&a,则必须执行5。仅仅**a还不够。