在前面一系列的字符串操作中,我们都是先定义一个固定大小的字符数组,然后根据所需,或拷贝、或连接、或格式化来为这个数组提供内容。固定大小的数组意味着在程序运行期间,数组所占用的内存是确定的(即划分了固定数量的内存),很多时候,这种方式简单好用。但是由固定二字也可以看到,这种方式也让它失去了灵活性。
假定我们现在要从磁盘上加载了一个新闻文件,那么,我们应该定义一个多大的字符数组才能保证完全容纳新闻内容呢?显然,这个大小很难确定。小了,内容会读取不全;大了,会浪费更多的内存。假如说我们有方法获得新闻内容的长度,然后分配同等大小的缓冲区(即字符数组),这该多完美!这便是动态内存分配一展身手的地方了。
malloc:动态分配指定数量的存储空间
我们秉承的是由简单到复杂的原则,因此这个示例仅用于说明malloc函数的使用。对于这种仅分配一个整数的情况,使用malloc完全不划算,不如直接定义一个变量简单好用。
free:释放malloc分配的存储空间
抛开虚拟内存等机制,计算机系统内存是有限的,如4GB、8GB。malloc用于向系统申请一定数量的内存,如果你的程序一味的申请内存供自己使用,那么系统可分配给其它程序的内存就会减少,到最后无内存可用,最终导致系统运行缓慢,不稳定等问题。显然,这种只索取不奉献的行为是不可取的因此,C语言提供了free函数,用于向系统返还借用的内存。
当你忘记使用free释放由malloc分配的内存时,表明程序存在”内存泄露“这一顽疾,因此对于上面的程序,我们在return 0之前,使用下面的代码进行完善。
动态数组
在实际开发中,像第一个示例那样为单个数据动态分配内存的情况很少见。更多时候,我们是分配一整块内存空间供程序使用。一整块所暗含的另一个意思就是这块内存区域中的地址是连续的,这一整块数据区域也可以称为缓冲区(buffer)。现在让我们回过头来解决文章开始提出的问题。
新闻的内容长度是58个字节,这是我提前使用strlen()测试出来的。因为C语言要求字符串必须以'0'结尾,因此我们在使用malloc分配内存时多分配了一个字节,用以存储这个标记。strcpy_s在拷贝完成后,会在目标串(message)后追加结束标记,因此不需要手动设置标记。
你可以尝试将例子中lengt+1全部变为length,再次运行时程序会中断,因为分配的缓冲太小了——只能够存储字符串,不能够存储最后一位结束符标记。
最后要说明的是:事实上malloc返回的地址类型是void*,但是在C语言环境中,可以由一个确切的类型直接持有此地址,如
int *pa = malloc(sizeof(int));
但是,通常为了通用性,建议将返回类型强制转换为对应的类型:
int *pa = (int*)malloc(sizeof(int));
这便是内存动态分配了!