概述
之前有同学在QQ上问我,C语言中的动态内存分配是怎么回事。
首先,我们来看看内存分配的概念,它是指在程序执行的过程中分配或者回收存储空间的方法。一般说来,内存分配方法分为静态内存分配和动态内存分配两种。在本文中,我们主要讨论动态内存分配。
要实现动态内存分配,就需要有执行这个操作的对象。C语言考虑得很周到,它为我们提供的两个标准库函数:malloc和free。
malloc和free函数简介
malloc函数
原型:void *malloc(size_t size);
简介:该函数在内存的动态存储区中分配一块长度为size字节的连续区域;如果分配成功,则函数的返回值为该区域的首地址;如果分配失败,则返回空指针值NULL。
free函数
原型:void free(void *ptr);
简介:该函数将之前用malloc开辟的内存空间释放掉,无返回值。
从形式上看,malloc和free函数都非常的简单,只有一个输入参数。下面,我们用具体的C代码来演示它们的用法。
C代码示例
/**********************************************************************
* 版权所有(C)2016, Zhou Zhaoxiong
*
* 文件名称:DynamicMemoryAlloc.c
* 文件标识:无
* 内容摘要:示例动态内存分配
* 其它说明:无
* 当前版本:V1.0
* 作 者:ZhouZhaoxiong
* 完成日期:20160901
*
**********************************************************************/
#include
#include
// 重定义数据类型
typedef signed int INT32;
typedef signed char INT8;
/****************************************************************
* 功能描述: 主函数
* 输入参数: 无
* 输出参数: 无
* 返回值: 0-执行成功 -1-执行失败
* 其他说明: 无
* 修改日期 版本号 修改人 修改内容
*-------------------------------------------------------------
* 20160901 V1.0 Zhou Zhaoxiong 创建
****************************************************************/
INT32 main(void)
{
INT8 szStrBuf[100] = {0};
INT8 *pStr = NULL;
// 为指针变量分配内存
pStr = malloc(100);
if (NULL == pStr) // 分配失败
{
printf("pStr is NULL!\n", pStr);
return -1;
}
memset(pStr, 0x00, 100);
// 打印初始化变量的值
printf("Step1: StrBuf=%s, pStr=%s\n", szStrBuf, pStr);
// 给变量赋值
memcpy(szStrBuf, "abcdefg", strlen("abcdefg"));
memcpy(pStr, "1234567", strlen("1234567"));
// 打印赋值之后的变量的值
printf("Step2: StrBuf=%s, pStr=%s\n", szStrBuf, pStr);
// 释放动态内存
free(pStr);
pStr = NULL;
// 打印释放动态内存之后的变量的值
printf("Step3: StrBuf=%s, pStr=%s\n", szStrBuf, pStr);
// --------------------
// 重新为指针变量分配内存
pStr = malloc(50);
if (NULL == pStr) // 分配失败
{
printf("pStr is NULL!\n", pStr);
return -1;
}
memset(pStr, 0x00, 50);
// 给变量赋值
memcpy(szStrBuf, "abcdefg", strlen("abcdefg"));
pStr = szStrBuf+1;
// 打印重新分配动态内存之后的变量的值
printf("Step4: StrBuf=%s, pStr=%s\n", szStrBuf, pStr);
// 再次释放动态内存
free(pStr);
pStr = NULL;
// 打印再次释放动态内存之后的变量的值
printf("Step5: StrBuf=%s, pStr=%s\n", szStrBuf, pStr);
return 0;
}
程序编译及运行
将上面编写的DynamicMemoryAlloc.c文件上传到Linux机器上,执行“gcc -g -oDynamicMemoryAlloc DynamicMemoryAlloc.c”命令,生成DynamicMemoryAlloc文件,然后执行“DynamicMemoryAlloc”命令,程序运行结果如下:
Step1: StrBuf=, pStr=
Step2: StrBuf=abcdefg, pStr=1234567
Step3: StrBuf=abcdefg, pStr=(null)
Step4: StrBuf=abcdefg, pStr=bcdefg
Step5: StrBuf=abcdefg, pStr=(null)
程序说明
第一,在main函数中,我们定义了两个变量:szStrBuf和pStr,其中szStrBuf在定义的时候已经给出了其占用内存空间的大小,因此该变量为静态内存分配;pStr变量在需要使用到的时候才分配内存,因此该变量为动态内存分配。
第二,我们使用malloc函数为变量分配动态内存,并使用free函数来释放动态内存,这两个函数要成对出现(即有一个malloc函数,就会有一个与之对应的free函数)。
第三,进行动态内存分配的变量的一个使用周期是在malloc函数和free函数之间,当一个变量的动态内存被释放掉之后,如果重新为它分配动态内存,那么它还是可以正常使用;例如,在main函数中,pStr变量先是被分配了100字节的空间,使用完成之后该空间就被释放掉了,当第二次为它分配50字节空间的时候,它又可以照常被使用了。
第四,从上面的代码可以看到,为进行动态内存分配的变量赋值的方式有两种,第一种是使用memcpy等函数进行赋值(如代码中的memcpy(pStr, “1234567”,strlen(“1234567”));),第二种是用另一个变量直接为它赋值(如代码中的pStr = szStrBuf+1;)。
总结
内存操作在C语言中占有非常重要的地位,而动态内存分配不当又是一个导致程序出现问题的主要原因之一。从本文中的代码可以看到,动态内存分配其实也没有什么特别困难之处,只要在需要用到某变量的时候为它分配一定的内存空间,在使用完成之后将该空间释放掉就行了。最为重要的是,malloc和free函数一定要配对出现。
最后再来举一个例子。上大学的时候,很多同学的生活费都是由家里给,有的家长在一学期或一学年开始的时候,就把整个学期或学年的生活费打到了卡上,而有的家长是按月打生活费的。这里的按学期或学年打生活费就相当于静态内存分配,而按月打生活费就相当于动态内存分配。