一、链表
链表是一种重要的且常见的数据结构,它是动态地进行存储分配的一种结构。如果要使用数组的话,我们需要提前进行定义数组的大小,这样的话就需要提前在内存空间上进行申请,如果申请的空间过大,那么内存得到浪费,如果申请的空间不够,会导致数据丢失等多种情况出现。链表中的每一个元素称为节点,节点包括两个部分,第一是数据域,第二是下一个节点的位置(即指针域)。链表中的元素不是连续存放,这样可以合理的使用内存的空间,也没必要需要完整的内存存储空间。优点在于:可以合理的利用和分配内存空间。缺点是:查找时的时间复杂度增加,必须要从头节点进行查找。
正式由于链表这种数据结构,所以只能用指针实现。节点中包含指针变量,用来指向地址。结构体变量中可以包含不同的变量,用来作为链表里的节点,再也合适不过了。
二、动态内存分配
动态内存分配就是指程序执行的过程中动态的分配活着回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。
三、c中实现内存管理的函数
1.malloc函数
原型
extern void *malloc(unsigned int num_bytes);
函数声明
void *malloc(size_t size);
备注:void*表示未确定类型的指针,void *可以指向任何类型的数据,更明确的说是指申请内存空间时还不知道用户是用这段空间来存储什么类型的数据(比如是char还是int或者其他数据类型)。
工作机制
malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要进行返回值的判断。
例子:
#include "stdio.h"
#include "malloc.h"//malloc()函数被包含在malloc.h里面
intmain(void)
{
char*a = NULL;//声明一个指向a的char*类型的指针
a = (char*)malloc(100*sizeof(char));//使用malloc分配内存的首地址,然后赋值给a
if(!a)//如果malloc失败,可以得到一些log
{
perror("malloc");
return-1;
}
sprintf(a,"%s","HelloWorld\n");//"HelloWorld\n"写入a指向的地址
printf("%s\n",a);//输出用户输入的数据
free(a);//释放掉使用的内存地址
return0;//例2有无内存泄露?
}
注:例1:对malloc申请之后没有检测返回值;例2:检测malloc返回值条件有误。
2.free函数
函数名:free
功能:与malloc()函数配对使用,释放malloc函数申请的动态内存。(另:对于free(p)这句语句,如果p是NULL指针,那么free对p无论操作多少次都不会出问题。如果p不是NULL指针,那么free对p连续操作两次就会导致程序运行错误。)
用法: voidfree(void *ptr);
释放哪些不使用的内存空间。
四、链表的使用
由于链表这种动态分配内存空间的优势,所以出现单链表,双链表,循环链表的应用等。利于进行数据的操作。