通过指针访问 C/C++ 中的多维静态数组

Access by pointer to multi-dimensional static arrays in C/C++

我知道,静态数组在内存中是连续布局的。 因此,例如,int T[10][10] 基本上与 int T[100] 的存储方式相同。 我可以通过多种方式访问​​索引 i、j 的元素,例如:

int T[10][10];
/*filling array*/
int i=3, j=7;
int x = T[i][j];
//EDIT - old and wrong: int * ptr = T;
int * ptr = &T[0][0];
int y = *(ptr + 10* i + j);

另一方面,当我自己创建动态分配的二维数组时:

int ** T;
T = malloc(10 * sizeof(int *));
for(i = 0; i < N; i++) 
    T[i] = malloc(10 * sizeof(int));

我的数组包含指向

的指针

很明显,我可以通过以下方式访问此数组的元素:

int i=3, j=7;
int x = *(*(T+i)+j);

现在我的问题是:它为什么以及如何适用于静态数组? 为什么

int T[10][10];
/*filling array*/
int i=3, j=7;
int x = *(*(T+i)+j);

return 对 x 很有价值,而这个 table 不包含指向数组的指针? *(*(T+i)) 在我看来应该没有意义,即使结束,它也应该 return T[0][i],因为 T 指向数组的第一个元素。编译器如何解释这个, * 不是这里的取消引用吗?开导我。

初学者:

int * ptr = T;

这实际上行不通,至少你的编译器不会对你大喊大叫。非常响亮地。正确的做法是:

int * ptr = &t[0][0];

这一点其实和你的问题很相关。

如您所知,在表达式中使用时,数组会退化为指针。例如:

char foo[10];

bar(foo);

当在表达式中使用时,就像函数的参数一样,数组会衰减为指向基础类型的指针。 foo 在这里给你一个 char *

然而,这是关键点:阵列只衰减一级。如果数组是二维数组,则数组不会衰减为基础值,在本例中为 int。二维数组引用衰减为指向一维数组的指针:

int T[10][10];
/*filling array*/
int i=3, j=7;
int x = *(*(T+i)+j);

此处发生的步骤顺序:

  1. T 衰减为指向 10 个整数数组的指针,或 int (*)[10]

  2. i 的加法使指针前进了给定的值。指针按所指向元素的大小前进。由于指针指向array of 10 integers,指针相应地前进。如果 i 为 2,则指针向前移动 "two arrays of 10 integers",松散地说。

  3. * 运算符采用 "pointer to an array of 10 integers" 并为您提供 "an array of 10 integers" 作为结果。换句话说:从 int (*)[10]int [10].

  4. 由于结果用在表达式中,即+ j的左操作数,而左操作数是数组类型,数组类型衰减为"pointer to int" .

  5. j 添加到结果中,并取消引用。

Why does

int T[10][10];
/*filling array*/
int i=3, j=7;
int x = *(*(T+i)+j);

return good value to x

魔法全在*(*(T+3)+7)(我已经转换成字面值了)

T 是 int 数组(大小为 10)的数组(大小为 10)。

当在表达式中使用 T 时,它会衰减为指向其第一个元素的指针,因此它会衰减为 "pointer to arrays (of size 10) of int".

向该指针添加一个整数将前进到数组的第四个元素。

所以T+3是一个指向10个整数数组的指针,特别是T中的第四个这样的数组。

*(T+3) 通过该指针间接给出类型 "array of 10 ints".

的左值

啊哈!那是表达式中使用的另一个数组 - 所以它会衰减为指向它的第一个元素的指针! (它 不会 sizeof 中衰减,因此 sizeof(*(T+3)) 通常为 40。)

(*(T+3) + 7)正好指向数组中的第8个元素,而...

*(*(T+3) + 7) 是一个 int 类型的左值!