双指针-获得意外的输出

时间:2019-10-30 21:55:18

标签: c pointers double-pointer

#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

请告诉我为什么得到不同的输出

1 个答案:

答案 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)导致未定义的行为。