二维数组及其动态内存分配

文章介绍了二维数组在内存中的分布和与一维数组的对应关系,强调在内存使用和访问效率上两者无本质差别。讨论了二维数组的下标式和指针式访问方法,并详细阐述了动态分配二维数组内存的正确方式,包括释放内存的顺序。还提到了非连续内存分配对于某些操作的限制,并给出列数不固定时的处理方法。

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

一、二维数组的基本概念

 二维数组的内存映像

从内存角度看,二维数组和一维数组一样,在内存中都是连续分布的多个内存单元,并没有本质差别,只是内存的管理方式不一样,如下图所示

 

一维数组int a[10]与二维数组int b[2][5]的对应关系为

一维数组

a[0]

a[1]

a[4]

a[5]

a[9]

二维数组

b[0][0]

b[0][1]

b[0][4]

b[1][0]

b[1][4]

一个一维数组a[m]可以表示为二维数组a[x][y](m = x * y),其中m是数组总元素个数,x和y分别是二维数组的行数和列数

任一二维数组中的元素a[i][j]在一维数组中对应的k为:k = i * y + j,即a[i][j] == a[k] == a[i * y + j]

二维数组和一维数组在内存使用效率、访问效率上是没有差别的(理想情况下)。在一些特定情况下(比如说矩阵、平面、显示器)用二维数组而不用一维数组,原因在于二维数组好理解、代码好写、利于组织。

二维数组的访问方式

下标式访问(便于理解):a[i][j]

指针式访问(数组本质):*(*(a + i) + j)

二维数组的动态内存分配

首先需要注意的是,不要这样一次性分配为数组内存空间:int **arr = (int**)malloc(n * m * sizeof(int));

正确的做法是先分配行,再分配列。释放内存的时候,要先释放列,再释放行。

注意,顺序反了的话,会把列的地址擦除,导致释放列时内存时找不到地址,程序崩溃。

正确的分配空间代码如下:

 int **arr = (int **)malloc(m*sizeof(int *));
 for(i=0;i<m;i++)
     {arr[i] = (int *)malloc(n*sizeof(int));}

正确的释放空间代码如下:

for (i = 0; i < m; i++)
     free(arr[i]);/*释放列*/

 free(arr);/*释放行*/

注:这种分配方式得到的其实并不是真正意义上的二维数组,因为其行与行之间的内存并不连续,虽然可以用下标arr[i][j]的方式访问,但当用指向该二维数组的指针来访问时候,不能通过指针值的增加来跨行获取元素,对所有元素清零:memset(arr, 0, m * n);是不可行的,必须每行分别清零。不过这种情况一般用的也不多,因此上述分配方式在大多数情况下的操作都能得到正确的结果。

当列数也不定时,需要多一个数组存放每一行的列数

int **arr = malloc(m * sizeof(int*)//分配指针数组的内存空间
	*returnSize =  m;//指针数组的长度,也即行数
*returnColumnSizes = malloc(sizeof(int) * m)//列数组,用来存放每一行的列数
for(int i = 0; i < m; i++){                              //为每一行分配内存空间
	arr[i] = malloc(sizeof(int) * n);                   //为第i行分配内存空间
	memset(arr[i], 0, sizeof(int) * n);               //初始化第i行全为零
 (*returnColumnSizes)[i] = n;                     //记录每一行的列数,也即元素个数
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值