C 将两个二维指针等价于二维数组

C 将两个二维指针等价于二维数组,c,pointers,C,Pointers,我正在尝试以下代码 #include<stdio.h> int main() { int A[3][4] = {{1,2,3,4},{5,6,7,8,},{9,10,11,12}}; int **t = &A[0]; //I do this or **t = A,I guess both are equivalent printf("%d %p\n\n",*t,A[0]); return 0; } #包括 int main() {

我正在尝试以下代码

#include<stdio.h>

int main()
{
    int A[3][4] = {{1,2,3,4},{5,6,7,8,},{9,10,11,12}};

    int **t = &A[0]; //I do this or **t = A,I guess both are equivalent


    printf("%d %p\n\n",*t,A[0]);

    return 0;

}
#包括
int main()
{
int A[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12};
int**t=&A[0];//我这样做或**t=A,我想两者是等价的
printf(“%d%p\n\n”,*t,A[0]);
返回0;
}
我所期望的是:

现在t是一个2d指针(指向指针的指针),它持有[0]的地址,而[0]又持有[0][0]的地址。所以*t应该给我A[0]的值,也就是A[0][0]的地址,**t应该给我A[0][0]的值,在本例中是1

我得到的是:

*t给出了1的值。试图找到**t是不可能的,因为它导致了分段错误

谁能告诉我为什么会这样

我尝试了下面的解释,但不确定它是否是“正确”的解释。 t保存[0]的地址,但由于A是数组,A[0]是数组指针(它“不完全”是指针),C不会为指针A或A[0]分配内存,这与其他指针变量不同。它只为整个阵列分配内存。因此A[0]和A[0](即A[0][0]的地址)的地址本质上是相同的,都属于同一屋檐下,不像是“单独的”实体。结果,t又间接地持有a[0][0]的地址,*t给出a[0][0]的值,即1

上面的解释正确吗?看起来有点奇怪。

数组不是指针。

嗯,甚至更多

多维数组不是双指针、三指针等。

因此,您所拥有的只是错误,您的程序多次调用未定义的行为,而没有任何您可以期待的。

假设数组在内存中是连续的,您可以这样重写示例:

int A[3][4] = {{1,2,3,4},{5,6,7,8,},{9,10,11,12}};
int *p = &A[0][0];

printf("%d %d %p\n", A[0][0], *p, (void *)p);
我尝试了下面的解释,但不确定它是否是“正确”的解释

不完全是,但有点接近

t
保存
A[0]
的地址,但由于
A
是一个数组,
A[0]
是一个数组指针

A[0]
是一个数组,具体来说,它的类型是
int[4]

(它“不完全”是指针),C不为指针
a
a[0]
分配内存,特别是与其他指针变量不同

数组和指针是本质上不同的实体类型。别把他们弄糊涂了

在大多数情况下,T数组类型的表达式被转换为指向T的指针类型的值(指向数组的第一个元素)这一事实肯定会造成混淆,但我们不能忘记这是一种转换。特别是,对于高维数组或数组的数组,数组的元素类型本身就是数组类型,因此转换的结果是指向数组的指针

它只为整个阵列分配内存。因此
A[0]
A[0]
(即
A[0][0]
的地址)的地址基本相同

不,它们本质上是不同的,一个-
A[0]
-是数组,
int[4]
,另一个-
&A[0]
-是指向四个
int
int(*)数组的指针。两者都不是
&A[0][0]

但是当
A[0]
转换为指向其第一个元素
&A[0][0]
的指针时,生成的地址通常与
A[0]
的地址相同(通常,指向对象的指针包含属于该对象的地址最低的字节的地址,并且由于
A[0]
属于(是其一部分)对象
A
,地址最低的对象,是
A[0]
的第一个字节,是
A
的第一个字节

所以
&A[0]
&A[0][0]
通常有相同的表示,但一个是
int(*)[4]
,另一个是
int*

两者都属于同一屋檐下,不像“独立”的实体。因此,
t
依次间接持有
a[0][0]
的地址,
*t
给出
a[0][0]
的值,即1

除了导致取消引用
t
未定义行为的类型不匹配之外,该部分或多或少是正确的。从形式上讲,未定义的行为允许任何事情发生


在实践中,如果
sizeof(int)==sizeof(int*)
,则取消引用
t
会将
int
1(即
A[0][0]
解释为地址,如果将其打印为
int
(另一个未定义的行为),则会打印出
1
。如果
sizeof(int*)==2*sizeof(int)
,这在64位系统上很常见,那么对
t
的解引用通常会将两个
int
s
A[0][0]
A[0][1]
一起解释为一个地址-
0x20000001
0x10000002
,这可能取决于端度。

数组不是指针。
int**
假设的内存布局不同于
int[x][y]
的内存布局。你的编译器听到这段代码时不是在痛苦地尖叫吗?@KerrekSB我肯定会的,就像内核的内存管理器模块一样。