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

c/c++ : 2-D array variable subscript

本文关键字:变量 下标 二维数组 c++      更新时间:2023-10-16
int a[3][3]={5};
printf("&a = %u n a = %u n*a = %un&a[0][0]=%dna[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吗?

  1. &a给出了数组的地址。它是int (*)[3][3]型的。容易。

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

  3. 对于*a,数组再次进行数组到指针的转换,以获得与之前相同的指向子数组的指针。然后将其解引用以获得子数组本身。然后,表示子数组的表达式也进行数组到指针的转换,为您提供指向第一个元素的指针。第一个元素的类型是int,因此指针的类型是int*。第一个元素的地址与它所在的子数组的地址相同,正如我们所看到的,子数组的地址与整个数组的地址相同。

  4. &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]

这些区域都从相同的地址开始,所以指针具有相同的值。

在C语言中,当数组涉及到表达式时(例如当传递给函数或指针算术时),它被隐式地转换为指针。因为您将a传递给printf,它被隐式转换为指向a的指针,这与&a相同。

您可能会感到困惑的是,*a看起来像一个相对于&a的双解引用,它返回数组的地址,所以*a应该在这个逻辑上得到a[0][0]的值。但事实并非如此。

"…"地址2359028的值不应该是5吗?"

是和不是。*a确实应该在地址a上给您对象。但是,在您的示例中,a的类型是int[3][3]。这意味着在这个间接层次上,地址a的对象(如果我们将a解释为指针)不是您错误地认为的5,它实际上是整个1D数组a[0]*a的类型是int [3],存储在*a的值同样是整个1D子数组a[0]

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

在这种情况下,如果您想访问5,则必须执行**a。仅*a是不够的。