C语言指向二维数组的四种指针以及动态分配二维数组的五种方式

本文详细介绍了在编程中如何根据应用场景动态分配二维数组,包括不同类型的指针指向、以及五种动态分配方法,如通过`calloc`分配并初始化二维数组,以及内存连续性优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

应用场景

当二维数组作为结构成员或返回值时,通常需要根据用户传递的参数来决定二维数组的大小,此时就需要动态分配二维数组。

可能指向二维数组的指针

如果现在有一个二维数组a[3][2],那么将有以下几种指针可以指向它:

//第一种:二维数组指针,指向整个二维数组
int (*ptr)[3][2]=&a;

//第二种:一维数组指针,指向二维数组第一行元素
int (*ptr)[2]=a;//or &a[0]

//第三种:int *型指针,指向二维数组第一行第一列的第一个元素
int *ptr=&a[0][0];//or *a

//第四种:int *型指针,指向二维数组第一行元素
int **ptr = calloc(3, sizeof(int *));
for (int i = 0; i < 3; ++i) {
   	*(ptr+i)=*(a+i);
}

动态分配二维数组

  • 方式一
int main(int argc, char **argv) {
    //初始化
    int (*ptr)[3][2] = calloc(3 * 2, sizeof(int));
    //赋值
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 2; ++j) {
            (*ptr)[i][j]=j;
        }
    }
    //打印
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 2; ++j) {
            printf("%d", (*ptr)[i][j]);
        }
        printf("\n");
    }
    return 0;
}
  • 方式二:
int main(int argc, char **argv) {
    //初始化
    int (*ptr)[2] = calloc(3 * 2, sizeof(int));
    //赋值
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 2; ++j) {
            *(ptr[i]+j)= j;
        }
    }
    //打印
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 2; ++j) {
            printf("%d", *(ptr[i]+j));
        }
        printf("\n");
    }
    return 0;
}

在应用场景中通常采用以下三种方式动态分配二维数组,因为这两种方式在声明二维数组时不需要知道二维数组的大小:

  • 方式三
int main(int argc, char **argv) {
	//初始化
    int *a = calloc(2 * 3, sizeof(int));
    //赋值
    for (int i=0;i<3;i++){
        for (int j = 0; j < 2; ++j) {
            *(a+2*(i-1)+j)=j;
        }
    }
    //打印
    for (int i=0;i<3;i++){
        for (int j = 0; j < 2; ++j) {
            printf("%d",*(a+2*(i-1)+j));
        }
        printf("\n");
    }
    return 0;
}

在这里插入图片描述

  • 方式四:使用此方式时有一些限制,因为以此方式分配的二维数组在内存上不连续
int main(int argc, char **argv) {
    //初始化
    int **ptr = calloc(3, sizeof(int *));
    for (int i = 0; i < 3; ++i) {
        *(ptr+i)=calloc(2, sizeof(int));
    }
    //赋值
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 2; ++j) {
            *(*(ptr+i)+j)=j;
        }
    }
    //打印
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 2; ++j) {
            printf("%d",*(*(ptr+i)+j));
        }
        printf("\n");
    }
    return 0;
}

在这里插入图片描述

  • 方式五:第四种方式的改进,内存连续
int main(int argc, char **argv) {
    //初始化
    int **ptr = calloc(3, sizeof(int *));
    *ptr = calloc(3 * 2, sizeof(int));
    for (int i = 1; i < 3; ++i) {
        *(ptr + i) = *ptr + i * 2;
    }
    //赋值
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 2; ++j) {
            *(*(ptr + i) + j) = j;
        }
    }
    //打印
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 2; ++j) {
            printf("%d", *(*(ptr + i) + j));
        }
        printf("\n");
    }
    return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

比特流梭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值