有了malloc函数的基本素养,就能够开辟一个一维动态数组。

而一个二维数组需要如何开辟呢?好像之前的malloc素养不够用了。


我们这里以开辟一个四行四列的二维数组为例。

指针数组开辟

先是开辟语句:

int** p = (int**)malloc(sizeof(int*) * 4);
for (int i = 0; i < 4; i++)
{p[i] = (int*)malloc(sizeof(int)*4);
}

首先我们开辟了内含四个指针的指针数组:

随后我们通过一个循环依次开辟他们的每个地址后所跟随的长度为四的整型数组:

这样也就使得我们能够通过每一个指针数组里的地址访问到相应的行列,每一个地址可以找到对应的行开头,通过行开头能够找都后续的列元素,而与之对应的长度为四的整型数组就可以存储该行所有的列元素,一个二维动态数组也就这样建好啦!

直接用指针数组来进行开辟十分符合我们的思维习惯,所以非常好理解,但是他也同样具备释放较为麻烦,并且无法保证一行最后一个元素与下一行第一个元素是连续存储的问题。

用指针数组开辟二维数组,一行最后一个元素与下一行第一个元素并不是连续存储:

且具备内存较难释放的问题:

我们需要先释放存储列元素的数组,然后释放我们之前所开辟的行指针数组。

//先释放每行的元素
for(int i=0; i<4; i++)
{free(p[i]);
}
//最后释放二级指针
free(p);

数组指针开辟

数组指针的开辟方法就解决了指针数组开辟释放难、行最后与下一行最前元素不连续的问题。

const int ROW = 4;
const int COL = 4;//数组指针列数可以用常量定义
int(*pp)[COL] = (int(*)[COL])malloc(ROW * COL * sizeof(int));

我们告诉了编译器该数组的列数为COL,接下来在开辟过程他会为我们做如下事情。

当编译器检测到我们列元素达到COL时,他会知道需要开始下一列了,于是将我们的十六个元素划分为了四个行 。

由于我们数组一次动态分配完毕,那自然我们一行的最后一个元素也就与下一行的第一个元素对应上了。

整个释放过程也变得及其简单,直接一个free(p)就完了,确实比原先的指针数组开辟简化不少。

但我们仍然需要注意到:他的列数是需要给出固定值的,这也是他的缺陷所在。

一维数组模拟开辟

其实这便是用二维数组的思维来管理一维数组,与其他的一维数组具体差异在于赋值与打印方面

int* ppp = (int*)malloc(ROW*COL*sizeof(int));
//赋值
for(int i=0; i<ROW ;i++)for (int j = 0; j < COL; j++){ppp[i * ROW + j] = i * ROW + j;}
//打印
printf("一维数组模拟二维数组\n");
for  (int i= 0; i < ROW; i++)for (int j = 0; j < COL; j++){printf("%-4d ", ppp[i * ROW + j]);if (j == COL - 1)printf("\n");}
free(ppp);

通过 i*ROW+j 的索引来映射他在二维数组中的位置

实验代码(供以调试)

#include<stdio.h>
#include<stdlib.h>//动态内存申请二维数组
//1.指针数组
//每一行元素地址连续   但是不能保证上一行的尾和下一行的头挨着
//int main()
//{
//  int** p = (int **)malloc(3*sizeof(int*));//竖的那个数组申请好了
//
//  for(int i=0; i<3; i++)
//  {
//      p[i] = (int*)malloc(4*sizeof(int));
//  }
//
//  for(int i=0; i<3; i++)
//  {
//      for(int j=0; j<4; j++)
//      {
//          printf("%p\n", &p[i][j]);
//      }
//  }
//  for(int i=0; i<3; i++)
//  {
//      free(p[i]);
//  }
//  free(p);
//  return 0;
//}//2.用数组指针
//int main()
//{
//  int (*p)[4] = (int(*)[4])malloc(3*4*sizeof(int));
//
//  for(int i=0; i<3; i++)
//  {
//      for(int j=0; j<4; j++)
//      {
//          printf("%p\n", &p[i][j]);
//      }
//  }
//  free(p);
//
//  return 0;
//}//3.用二维数组的思想去管理申请的一维数组
//int main()
//{
//  int *p = (int*)malloc(3*4*sizeof(int));
//
//  for(int i=0; i<3; i++)
//  {
//      for(int j=0; j<4; j++)
//      {
//          p[i*4+j] = 1;
//          printf("%p\n", &p[i*4+j]);
//      }
//  }
//
//  free(p);
//
//  return 0;
//}int main()
{//动态开辟二维数组//1  指针数组开辟// 释放较为麻烦,并且无法保证一行最后一个元素与下一行第一个元素是连续存储的
//  int** p = (int **)malloc(3*sizeof(int*));//竖的那个数组申请好了
//
//  for(int i=0; i<3; i++)
//  {
//      p[i] = (int*)malloc(4*sizeof(int));
//  }int** p = (int**)malloc(sizeof(int*) * 4);for (int i = 0; i < 4; i++){p[i] = (int*)malloc(sizeof(int)*4);}for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){p[i][j] = j;}}printf("指针数组开辟二维数组\n");for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){printf("%d ",p[i][j]);if (j == 3)printf("\n");}}//先释放每行的元素for(int i=0; i<4; i++){free(p[i]);}//最后释放二级指针free(p);//2. 数组指针开辟二维数组// int (*p)[4] = (int(*)[4])malloc(3*4*sizeof(int));
//
//  for(int i=0; i<3; i++)
//  {
//      for(int j=0; j<4; j++)
//      {
//          printf("%p\n", &p[i][j]);
//      }
//  }//释放简单,一行最后一个元素与下一行第一个元素连续存储,但列数需固定,无法自定义列数const int ROW = 4;const int COL = 4;//数组指针列数可以用常量定义printf("数组指针开辟二维数组,打印地址\n");int(*pp)[COL] = (int(*)[COL])malloc(ROW * COL * sizeof(int));for(int i=0; i<4; i++){for(int j=0; j<4; j++){printf("%p\n", &pp[i][j]);}}free(pp);//3. 一维数组当作二维数组来管理//可使用变量来作为行数和列数,释放简单,但脑海里需要绕弯子易出错,赋值与打印十分麻烦int* ppp = (int*)malloc(ROW*COL*sizeof(int));//赋值for(int i=0; i<ROW ;i++)for (int j = 0; j < COL; j++){ppp[i * ROW + j] = i * ROW + j;}//打印printf("一维数组模拟二维数组\n");for  (int i= 0; i < ROW; i++)for (int j = 0; j < COL; j++){printf("%-4d ", ppp[i * ROW + j]);if (j == COL - 1)printf("\n");}free(ppp);
}

 实验结果:

(如有问题,欢迎指正)

C语言(动态开辟二维数组 指针数组、数组指针、一维数组模拟开辟)相关推荐

  1. c语言动态生成二维数组,C语言 动态创建二维数组

    /*C语言 如何动态创建二维数组 转化为一维数组申请数组,创建和释放都比较简单 */ #include #include #include #define RANK 10 #define COLUMN ...

  2. C语言-动态创建二维数组

    文章目录 1 前言 2 动态创建的实现方法 2.1 方法1(适用于二级指针传递) 2.2 方法2(模拟C语言数组的储存方式) 1 前言 参照我之前的一篇文章 二维数组做函数的参数 文章中提到,当我们想 ...

  3. C语言动态创建二维数组

    在编程中有时需要使用二维数组作为buffer,下面是我写的一个二维数组的demo. 这里面涉及到几个内存操作的知识点,一个一个的来讲. 1. 创建两个1维数组,用于给二维数组填充值的时候使用. /*2 ...

  4. 创建二维数组(一维长度3,二维长度6),值为一维数组和二维数组索引值的积

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  5. 动态开辟二维数组的两种方案及位体

    动态开辟二维数组的两种方案及位体 一.在静态二维数组中查询数据 二.动态开辟二维数组空间 1.用二级指针的方式开辟 2.用结构体的方式开辟 三.位体 先来回顾一下动态开辟一位数组的方法: #inclu ...

  6. [ 1001] 动态开辟二维数组的说明

    开辟二维数组的说明 图解  [1][][][][] [2][][][][] [3][][][][] void main() { int i,j; /*注意申请的指针格式  先创建的是1,2,3首地址为 ...

  7. (c语言)编程输出二维数组中元素的最大值,要求用指针实现。

    (c语言)编程输出二维数组中元素的最大值,要求用指针实现. #include<stdio.h> #include<stdlib.h> #define N 6 //行数 #def ...

  8. C++ 动态开辟二维数组的的方法

    近日写到一个程序,用到了要动态开辟二维数组,一想,自己就会两种.一者:用new在堆上开辟:二者:用vector开辟.技巧没有多少,但是确实是折腾了我半天!首先,大家去网上搜一下,动态开辟二维数组的文章 ...

  9. C语言 用malloc开辟二维数组

    用malloc可以开辟空间 对于二维数组来说 我们开辟的话同样也可以用malloc来开辟 以下用不同方法开辟二维数组均为开辟三行四列为的二维数组. 1.利用指针数组 存储示意图: 代码如下: int ...

  10. malloc动态创建二维数组(C语言)

    c语言用malloc动态创建二维数组 #include <stdio.h> #include <stdlib.h> void fun(int m,int n){//行数,列数 ...

最新文章

  1. mysql的driver和url_数据库连接driverClass和jdbcUrl大全
  2. MySQL 中日志的面试题总结
  3. 懒加载Lazy Loading
  4. c语言if语句教学设计,c语言if语句教学设计.pdf
  5. opencv-api convexityDefects
  6. linux django 安装mysql_Linux下安装Python3和django并配置mysql作为django默认服务器
  7. redis底层数据结构
  8. ST电机库5.0完全开源对电机控制软件工程师有何影响?
  9. 什么软件可以搜c语言的答案,跪求C语言答案
  10. 【网络攻防】常见的网络攻防技术——黑客攻防(通俗易懂版)
  11. 程序员面试逻辑题解析
  12. 【爬虫】身份证前6位区域划分编码爬取
  13. 铺铜需要把agnd和dgnd分开_AGNDDGND 分析
  14. 电脑分辨率怎么调?教你调整电脑屏幕分辨率
  15. PM2.5浓度数据集(1998-2016年)
  16. 按照网络规模来分,服务器分为哪几类?
  17. [16-8-1]每日总结
  18. 消费返利模式的众筹玩法轻松无压力
  19. Android第三方支付
  20. 阿里云构建仓库与镜像

热门文章

  1. vue部署到服务器 路由刷新找不到
  2. Windows Server 2008 R2 官方原版下载大全
  3. 理光2014ad扫描服务器响应,理光mp2014ad扫描驱动和打印驱动
  4. 光纤猫可做无线打印服务器吗,光猫自带的天线,这些天线都有什么用呢?是无线功能吗?...
  5. Linux下oracle数据库备份方案
  6. SSH框架的详细介绍
  7. 开源项目推荐:office办公软件,绘图软件
  8. 基于bootstrap,个人简历网页模板,响应式布局
  9. 计算机组装与维护选教材,计算机组装与维护校本教材.doc
  10. RGB 256颜色表代码表