通过指针访问 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);
此处发生的步骤顺序:
T
衰减为指向 10 个整数数组的指针,或 int (*)[10]
i
的加法使指针前进了给定的值。指针按所指向元素的大小前进。由于指针指向array of 10 integers
,指针相应地前进。如果 i
为 2,则指针向前移动 "two arrays of 10 integers",松散地说。
*
运算符采用 "pointer to an array of 10 integers" 并为您提供 "an array of 10 integers" 作为结果。换句话说:从 int (*)[10]
到 int [10]
.
由于结果用在表达式中,即+ j
的左操作数,而左操作数是数组类型,数组类型衰减为"pointer to int" .
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 类型的左值!
我知道,静态数组在内存中是连续布局的。
因此,例如,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);
此处发生的步骤顺序:
T
衰减为指向 10 个整数数组的指针,或int (*)[10]
i
的加法使指针前进了给定的值。指针按所指向元素的大小前进。由于指针指向array of 10 integers
,指针相应地前进。如果i
为 2,则指针向前移动 "two arrays of 10 integers",松散地说。*
运算符采用 "pointer to an array of 10 integers" 并为您提供 "an array of 10 integers" 作为结果。换句话说:从int (*)[10]
到int [10]
.由于结果用在表达式中,即
+ j
的左操作数,而左操作数是数组类型,数组类型衰减为"pointer to int" .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 类型的左值!