C 语言编程经常需要用到数组,若实现能确定数组的长度,非常好实现数组的定义。但是,如果数组的长度需要经过程序运行后才能确定,动态内存分配就比较合适了。开发时,常用的动态内存分配都是一维的,今天需要用到二维动态内存分配,将过程记录在此。
二维动态内存分配要解决的问题
假设,程序运行过程中,会产生一串数字,长度不固定,需要将这串数字存储下来。
显然,数组非常适合存储这串数字,然而因为长度不能事先确定,所以使用常规的定义数组方法只能定义一个足够大的数组,这往往会造成资源的浪费。动态内存分配非常适合解决事先不能确定长度的数组的定义,动态内存分配很简单,C 标准库提供了 malloc
函数分配内存和 free
函数释放内存。
在上个问题基础上,要求存储 5 串这样的数字。
为了解决这个问题,当然可以用 5 个数组存储,但是如果想将它们连接起来,该怎么做呢?二维数组就非常适合了。上面已经提到,因为每串数字的长度不能确定,较难使用常规的数组定义方法,这就需要二维动态内存分配了
。
C语言实战
在实现二维动态内存分配前,先来看一维的,假设要存的数字串是字符串。
// 文件名 t.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* buf1 = (char*)malloc(32); // 分配 32 字节内存
if(!buf1)
return -1;
sprintf(buf1, "this is buf1");
printf("%s\n", buf1);
free(buf1); // 释放内存。
buf1 = NULL;
return 0;
}
buf1 = NULL;
有这句的原因是,释放后,buf1 指针仍然可用,但是其指向的内容已经不可知,为了避免造成未知错误,让其指向 NULL
。
编译,执行之,结果如下
$ gcc -o t t.c
$ ./t
this is buf1
非常简单。下面解决问题2:
在上个问题基础上,要求存储 5 串这样的数字。
思路是这样的:假设已经分配好 5 个类似于 buf1 的内存,为了将它们连接起来,只要再分配一个长度为 5 的数组,数组单元存储 buf1, buf2, buf3, buf4, buf5 即可。
按照这样的思路,可以按照下面的方法实现:
char* bufs[5];
bufs[0] = buf1;
bufs[1] = buf2;
...
但是,如果要求存 n 串数字串呢,而 n 也事先不能确定呢?这就需要二维动态内存分配了。
代码如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
typedef char* schar;
schar* bufs = (schar*)malloc(5*sizeof(schar));
if(!bufs)
return -1;
bufs[0] = (schar)malloc(16);
bufs[1] = (schar)malloc(17);
bufs[2] = (schar)malloc(18);
bufs[3] = (schar)malloc(19);
bufs[4] = (schar)malloc(15);
for(int i=0; i<5; i++){
sprintf(bufs[i], "this is bufs[%d]\n", i);
printf("%s", bufs[i]);
}
for(int i=0; i<5; i++){
free(bufs[i]);
bufs[i] = NULL;
}
free(bufs);
bufs = NULL;
return 0;
}
执行之,得到结果如下
$ gcc -o t t.c
$ ./t
this is bufs[0]
this is bufs[1]
this is bufs[2]
this is bufs[3]
this is bufs[4]
一切符合预期。