二级指针创建二维数组

学习了数组,我们知道定义数组,可以申请到一段内存空间,可以在内存空间中存储数据。例如:

char a[3][16] = {0};

此时定义了一个二维数组,该数组是一块连续的内存空间。此时,a[0]元素是一维数组,有16个字节的内存空间。同理,a[1]、a[2]也是一维数组,都占用16个字节的存储空间。程序测试例子如下:

c语言二维数组与指针(如何使用二级指针来创建二维数组)(1)

程序运行结果如下:

c语言二维数组与指针(如何使用二级指针来创建二维数组)(2)

在上面的例子中,使用数组的定义,数组的“维数”必须是固定的。例如,第一维是3,是有3个元素,即a[0]、a[1]、a[2]这样的三个元素;而且,每一个一维元素占有16个字节的存储空间。例如,a[0]占有16个字节的存储空间。

那么,如果我们开发一个网络通信程序,有一个网络数据包发送过来。那么,网络数据包的长度是不确定的,有可能是5个字节,也有可能是300个字节。

那么,如果我们使用数组来定义一个内存块,就尽量定义大容量的数组,才可以存放完整个网络数据包。例如:

char buf[512];

此时,定义一个数组,该数组的容量是512个字节。但是,如果网络数据包很大,是几千个字节,那么,就需要申请更大容量的内存块。

那么,在这种情况下,我们可以“动态申请”内存。修改上面的例子,程序测试例子如下:

c语言二维数组与指针(如何使用二级指针来创建二维数组)(3)

程序运行结果如下:

c语言二维数组与指针(如何使用二级指针来创建二维数组)(4)

可以看到,我们定义了一个数组,如下:

char* a[3] = {0};

该数组的元素是char*类型的指针类型,它可以指向一块内存的首地址。然后,我们再为数组的每一个元素申请内存块,如下:

a[0] = (char*)calloc(1, size);

a[1] = (char*)calloc(1, size);

a[2] = (char*)calloc(1, size);

此时,a[0]、a[1]、a[2]元素就存放一个内存块的首地址,而且,该内存块的容量是size个字节。

所以,在程序中,我们可以动态修改size变量的大小,就可以申请不同容量的内存块。满足程序设计中动态、弹性使用内存块的需求。

在上面的例子中,我们定义了数组a[3]的容量是3个元素,那么,如果我们的程序又需要大量的内存,3个元素无法满足,而且我们需要动态申请,那么,可以修改代码如下:

c语言二维数组与指针(如何使用二级指针来创建二维数组)(5)

程序运行结果如下:

c语言二维数组与指针(如何使用二级指针来创建二维数组)(6)

可以看到,我们定义一个二级指针 char** a,然后,给它申请内存,如下:

a = (char**)calloc(num, sizeof(char*));

此时,指针 a 指向一个内存块的首地址,该内存块有num个元素,每个元素占用char*类型变量的大小。所以,每个元素可以存放一个char*类型的指针变量值。所以,我们可以动态修改num变量,动态申请内存块的容量。

例如,设置num = 300,此时,可以使用a[299]这样的元素,再可以执行:

a[299] = calloc(1, size);

那么,a[299]这个元素又可以指向一块内存块,该内存块占用size个字节的内存。

所以,这里我们介绍了使用二级指针,可以创建一个二维数组的内存块。而且,可以动态修改申请内存块的容量。

注意,使用malloc、calloc等动态申请内存块的函数,申请了内存之后,不再使用该内存时,需要手动调用free函数来释放内存块。

动态申请的内存块,如果不调用free()函数来释放,造成内存泄漏,内存无法回收,程序没有足够的内存空间可以继续运行。程序异常。

,