#include <stdio.h>
#include <stdlib.h>
int main()
{
int a[3][3]={{0,1},{2,3},{5,6}},**b,i,j;
b=(int **)calloc(3,sizeof(int *));
for(i=0;i<3;i++)
{
b[i]=(int *)calloc(3,sizeof(int));
}
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
b[i][j]=(i+1)*(j+1);
}
}
printf("%d %d %d %d\n",*(*a+4),**a+4,*(*b+4),**b+4);
printf("%d %d %d %d\n",*(a[2]-2),**(a+2),*(b[2]-2),**(b+2));
return 0;
}
我得到的输出:
3 4 2 5
3 5 6 3
我应该得到:
3 4 4 5
3 5 4 3
原因:
*(*b+4) = *(b[0]+4)
。 b[0]+4
指向b[1][1]
,因此该值应为4
,即1,1
位置处矩阵的值
*(b[2]-2)
,现在b[2]-2
指向b[1][1]
,因此值应再次为4
请告诉我为什么得到不同的输出
答案 0 :(得分:1)
当声明一个像a[3][3]
这样的二维数组时,整个数组是连续的,因此a[0][2]
之后紧跟a[1][0]
。在a
上使用指针算术时,只要您停留在整个a
数组中,就可以依靠这种跨行的能力。
但是,当您使用指针数组时,没有理由期望每一行都与上一行连续。每个调用分配给malloc()
的内存与先前的调用无关。另外,malloc()
必须确保内存适合任何数据类型;如果您分配的大小不是此大小的倍数,则它们不可能是连续的。许多动态内存分配器在分配之前存储簿记信息(例如分配的大小,以便free()
知道要回收多少内存),这样也可以防止分配连续。
访问超出分配大小的内存是未定义的行为。由于b[0]
指向3 int
的分配,因此b[0]+4
在此分配之外,并且*(b[0]+4)
导致未定义的行为。