【C语言速成】13. 动态内存、malloc()函数和free()函数
动态内存概述
在开发C语言程序时使用动态内存技术,就能让程序在运行时按需分配和释放内存,不受到编译前在代码里写死了的固定大小内存的限制。
一般来说,当程序需要处理一些不确定大小或数量的数据时,就应该使用动态内存。一个典型的例子就是当你需要创建一个数组,却确定不了它的长度时,可以等到长度确定后使用动态内存来分配初始的内存空间,以后再按需扩容或缩小它。
sizeof运算符
介绍
sizeof运算符接受一个参数,返回参数的数据类型在当前机器上占用的字节数。参数可以是一个数据类型,也可以是一个实际的变量。sizeof返回数据的类型是size_t
(大多数情况下等价于unsigned long
,具体情况由机器和编译器决定)。
sizeof长得像一个只有一个参数的、返回一个size_t
型整数的函数,但是它本质上不是函数,具体原因目前不用了解。
使用
输出int型数据在当前机器上占用的字节数:
printf("%zd", sizeof(int)); // %zd用于对应size_t类型的数据
程序输出:4
输出long型数据在当前机器上占用的字节数:
long a = 9999999999;
printf("%zd", sizeof(a));
程序输出:8
malloc()函数
介绍
malloc函数接受一个指定的整数参数,给程序分配相应字节数的内存,返回指向新分配的那段内存开头地址的无类型指针(类型为void*
)。
注意
- 使用malloc函数和下文的free函数需要在代码开头使用
#include
预处理语句包含头文件malloc.h
或stdlib.h
。 - 如上文所述,malloc函数返回的指针没有保存数据类型,所以需要强制转换成需要的类型。
使用
在动态内存区分配一个int型变量的空间,使用一个指向int型变量的指针给它赋初始值
int* a = (int*) malloc(sizeof(int));
*a = 1234;
printf("%d", *a);
程序输出:1234
free()函数
介绍
free函数接受一个指针类型的参数,向系统归还这个指针所指的内存段。
注意
- free函数只能释放先前用malloc函数分配的内存段。
- 不能对同一段内存接连调用free函数。
- 如果一个指针所指的内存段被free函数释放了,不要在这个指针在被重新指向别的变量之前继续用它。
- 如果你使用malloc函数分配过内存,那么一定要在不再使用那些内存时使用free函数归还内存。C语言程序是不会自动释放malloc分配的内存的,总是分配内存而不释放会浪费资源,导致系统变卡甚至让程序崩溃。
使用
释放先前用malloc函数分配的那段内存
free(a); // a所指的内存被释放了
printf("%d", *a); // a所指的内存现在不属于a,解引用它得不到有效数据,程序也可能会直接崩溃
程序输出:1619033671
NULL关键字
C语言有一个叫“NULL”的关键字(由预处理语句定义的)来表示内存地址0,把它赋值给指针相当于让指针不指向任何数据(或者说把它变成空指针)。当使用完一段内存并用free释放后,应该将指向这段内存的指针的值设为NULL来避免误用被释放的内存,因为大部分情况下程序检测到对空指针进行解引用时会直接崩溃而不是继续带着无效的数据运行下去。
int* d; // 创建一个指针
d = (int*)malloc(sizeof(int)); // 分配一个int大小的内存,让d指向这段内存
*d = 1234; // 解引用d,设置目标位置内存的值
printf("%d", *d); // 输出1234
free(d); // 释放d所指的内存,现在d所指的内存里的数据无效
printf("%d", *d); // 不一定输出1234
d = NULL; // 让d指向内存地址0(将d设为空指针)
printf("%d", *d); // 程序运行到这会崩溃,因为不能解引用空指针
综合示例
输入一个正整数n,之后再输入n个正整数,然后让程序把刚才输入的n个正整数以跟输入顺序相反的顺序输出
代码
输入输出
【你】4
【你】9 8 7 6
【电脑】6
【电脑】7
【电脑】8
【电脑】9