C 编程二维数组内存布局

Kas*_*iff 2 c arrays multidimensional-array data-structures

考虑下面的 C 代码。

#include <stdio.h>
int main(){
   unsigned int x[4][3] = {{1, 2, 3}, {4, 5, 6},
                       {7, 8, 9}, {10, 11, 12}};
   printf("%u, %u, %u", x+3, *(x+3), *(x+2)+3);
   printf("\n%u, %u, %u", x,&x,*x);
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在,每个 printf 语句都打印相同的值,如下所述。

6356724, 6356724, 6356724
6356688, 6356688, 6356688
Process returned 0 (0x0)   execution time : 0.128 s
Press any key to continue.
Run Code Online (Sandbox Code Playgroud)

我想知道每个 printf 语句的结果如何相同。这是我对二维数组内存布局的理解。 二维数组内存布局

现在我相信 x+3 指的是( x + 3 * 指针算术所需的大小) = 24 和 *(x +3 ) = *(24) = 2036 的基地址,但第一个 printf 语句打印 2036 的情况并非如此, 2036 2036 。我想直观地了解二维数组是如何组织的。

n. *_* m. 5

每当提到数组时,它都会衰减为指向其第一个元素的指针(除了目前不感兴趣的少数情况)。

为什么x&x*x都打印得一样?这是因为数组本身,它的第一个元素(如果是二维数组,则它的第一个元素的第一个元素,它本身就是一个一维数组)都具有相同的地址。

所以:

  • &x是指向数组的指针
  • x是数组本身,它衰减到其第一个元素的指针
  • *x是数组的第一个元素,数组本身就是一个数组,因此它衰减到第一个元素(1, 2, 3}的指针

所有这些指针都有不同的类型,但指向相同的地址。

x+3和 也会发生同样的情况*(x+3)。首先,x衰减为指针,然后执行指针算术。说y = x + 3, soy*y指向相同的地址,就像x和 *x` 一样(见上文)。

关于什么*(x+2)+3?嗯,*(x + 2)is 本身就是一个包含 3 个元素的数组。So*(x+2)+3指向超出数组末尾*(x + 2)的一个元素。然而,这个不存在的元素有一个地址,并且它与数组的第一个元素的地址相同*(x + 3)——因为*(x + 2)*(x + 3)在数组中彼此相邻x