为什么对二维数组应用间接寻址会给出一个指针?
Why application of indirection to a two-dimensional array gives a pointer?
在阅读了该站点上的一些帖子后,我意识到 C 中的数组并不像我最初认为的那样只是一个常量指针,它本身是一种独特的类型,但在大多数情况下,数组“衰减”为一个常量指针到数组的第一个元素。由于这些新信息,我的脑海中出现了一个问题。假设我们有一个二维的A[10][10]。为什么表达式 *A 的结果是指向数组第一个元素的指针?我认为在这个表达式中,A 衰减到指向数组第一个元素的常量指针 A[0][0],然后间接寻址的应用应该给我们A[0][0]的值,但实际上它仍然给我们数组第一个元素的地址。当然,我的逻辑或我对数组或指针的理解有问题,所以我哪里错了?
提前致谢。
A decays to a constant pointer to the first element of the array
A[0][0]
不,不是。为什么?
C 标准指定 *(pointer + integer) == pointer[integer]
,因此 *A
等同于 *(A + 0)
,即 A[0]
。 A[0]
不会 给你元素 A[0][0]
只有一维数组,它将衰减到指向该数组第一行的第一个元素的指针。
*A 或 A[0] 本身是一个包含 10 个元素的数组,并且数组始终由指向其第一个元素的指针表示。然而,A[10][10](比方说一个整数数组)实际上是一个内存块,其中包含 100 个整数,第一行的 10,然后是第二行的 10,依此类推。但是如果表达式 *A 或 A[0] 将 return 一个 int 而不是指向该行的 ptr,那么就不可能使用表达式 A[0][0],对吗?
但是,因为这样的多维数组是单块内存,所以也可以将其转换为指针,然后使用这种表达式访问它:
((int *)A)[iRow * 10 + iCol];
相当于表达式:
A[iRow][iCol];
但是,如果二维数组可以这样声明的话:
int main()
{
int A[10][10] = { 0 };
A[9][9] = 9999;
printf("==> %d\n", ((int *)A)[9 * 10 + 9]); //==> 9999
return 0;
}
如果内存可能由单独的字节块组成(可能需要多次调用 malloc),就像这种表达式一样:
int * A[10]; // or
int ** A;
A
的第一个元素是A[0]
,不是A[0][0]
。
这是因为A
是十个东西的数组。 C 没有二维数组作为主要类型。具有多个维度的数组被派生或构造为多层数组。对于编译器,结果类型仍然只是一个数组,其元素恰好是进一步的数组。
因此,在*A
中:
A
被转换为指向其第一个元素的指针。该指针是 &A[0]
,因此 *A
变为 *&A[0]
。
*
和&
取消,所以表达式变成A[0]
.
A[0]
是一个包含十个元素的数组,因此它被转换为指向其第一个元素的指针,&A[0][0]
.
在阅读了该站点上的一些帖子后,我意识到 C 中的数组并不像我最初认为的那样只是一个常量指针,它本身是一种独特的类型,但在大多数情况下,数组“衰减”为一个常量指针到数组的第一个元素。由于这些新信息,我的脑海中出现了一个问题。假设我们有一个二维的A[10][10]。为什么表达式 *A 的结果是指向数组第一个元素的指针?我认为在这个表达式中,A 衰减到指向数组第一个元素的常量指针 A[0][0],然后间接寻址的应用应该给我们A[0][0]的值,但实际上它仍然给我们数组第一个元素的地址。当然,我的逻辑或我对数组或指针的理解有问题,所以我哪里错了?
提前致谢。
A decays to a constant pointer to the first element of the array A[0][0]
不,不是。为什么?
C 标准指定 *(pointer + integer) == pointer[integer]
,因此 *A
等同于 *(A + 0)
,即 A[0]
。 A[0]
不会 给你元素 A[0][0]
只有一维数组,它将衰减到指向该数组第一行的第一个元素的指针。
*A 或 A[0] 本身是一个包含 10 个元素的数组,并且数组始终由指向其第一个元素的指针表示。然而,A[10][10](比方说一个整数数组)实际上是一个内存块,其中包含 100 个整数,第一行的 10,然后是第二行的 10,依此类推。但是如果表达式 *A 或 A[0] 将 return 一个 int 而不是指向该行的 ptr,那么就不可能使用表达式 A[0][0],对吗?
但是,因为这样的多维数组是单块内存,所以也可以将其转换为指针,然后使用这种表达式访问它:
((int *)A)[iRow * 10 + iCol];
相当于表达式:
A[iRow][iCol];
但是,如果二维数组可以这样声明的话:
int main()
{
int A[10][10] = { 0 };
A[9][9] = 9999;
printf("==> %d\n", ((int *)A)[9 * 10 + 9]); //==> 9999
return 0;
}
如果内存可能由单独的字节块组成(可能需要多次调用 malloc),就像这种表达式一样:
int * A[10]; // or
int ** A;
A
的第一个元素是A[0]
,不是A[0][0]
。
这是因为A
是十个东西的数组。 C 没有二维数组作为主要类型。具有多个维度的数组被派生或构造为多层数组。对于编译器,结果类型仍然只是一个数组,其元素恰好是进一步的数组。
因此,在*A
中:
A
被转换为指向其第一个元素的指针。该指针是&A[0]
,因此*A
变为*&A[0]
。*
和&
取消,所以表达式变成A[0]
.A[0]
是一个包含十个元素的数组,因此它被转换为指向其第一个元素的指针,&A[0][0]
.