我试图理解二维数组中的某些东西。
int A[2][3] = {{20, 30, 40}, {50, 60, 70}};
printf("%p\n",A); // Output is 0x7ffde7e966d0
printf("%p\n",*A); // Output is 0x7ffde7e966d0
我知道这两个地址有不同的范围,A + 1
和 *A + 1
是完全不同的地址,但我的主要误解是在使用解引用运算符时它应该产生一个值而不是地址。
看起来二维数组的名称就像一个指向自身的指针。
我试过这段代码
int *p = &p;
printf("%p\n",p); // Output is 0xfff1c9a94b0
printf("%p\n",*p); // Output is 0x1c9a94b0
编译器给我一个警告
从不兼容的指针类型“int **”初始化“int *”[-Wincompatible-pointer-types]
但代码运行如上所示。如果我尝试添加更多星号 int **p = &p;编译器警告将类似于来自不兼容指针类型“int ***”的“int **”
奇怪的是,从右到左的前 8 或 7 位数字的输出地址始终相同。
在这种情况下,我们可以称 *p
是一个指向它自身的指针吗?
最佳答案
您的 printf
调用有些不正确:%p
需要一个 void *
,它既不是 A
也不是 *A
是,即使在衰减到指向其第一个元素的指针之后也是如此。
考虑这个简单的例子:
#include <stdio.h>
int main() {
int A[2][3] = {{20, 30, 40}, {50, 60, 70}};
printf("&A=%p &A+1=%p sizeof(*&A)=%zu\n", (void*)(&A), (void*)(&A + 1), sizeof(*&A));
printf(" A=%p A+1=%p sizeof( *A)=%zu\n", (void*)( A), (void*)( A + 1), sizeof( *A));
printf("*A=%p *A+1=%p sizeof(**A)=%zu\n", (void*)(*A), (void*)(*A + 1), sizeof(**A));
return 0;
}
在我的系统上,输出是:
&A=0x7fff5b9877a0 &A+1=0x7fff5b9877b8 sizeof( A)=24
A=0x7fff5b9877a0 A+1=0x7fff5b9877ac sizeof( *A)=12
*A=0x7fff5b9877a0 *A+1=0x7fff5b9877a4 sizeof(**A)=4
&A
和&A + 1
产生的地址的区别是sizeof(*&A)
,与相同>sizeof(A)
...接下来的 2 个语句也是如此。
A
是一个由 2 个 3 个整数组成的数组。在内存中,它被实现为一个 24 字节的序列,6 个整数中的每一个都有 4 个字节(在具有 32 位 int
和 8 位字节的系统上,这是当今最常见的值)。这 24 个字节位于内存中由定义位置确定的特定地址。数组 A
,它的第一个元素 A[0]
(它本身是一个数组,可以称为 *A
,甚至 0[A]
)和A[0][0]
都位于同一个地方,第一个int
的第一个字节的地址.
关于指针可以指向自身吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72247507/