前言
C语言堆内存管理
引入头文件
作用域
1 2 3 4 5 6 7
| int a = 0; int main() { int a = 0; { int a = 0; } }
|
变量的种类
自动变量
- 代码块内部定义的都是自动变量,只不过平常我们会省略
auto
关键字
寄存器变量
静态变量
- 静态变量放在代码块内或代码块外都可以
- 静态变量只初始化一次,在程序加载到内存的时候就创建,直到程序运行结束才销毁
全局变量和全局函数
- 全局变量和全局函数可以跨文件使用
- 静态全局变量和静态全局函数只能在定义它的文件内使用
a.c
1 2 3 4 5 6 7 8
| int a = 0;
int b() { ... }
|
b.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| extern int a;
extern int b();
int main() { a = 1; b(); return 0; }
|
在堆中开辟一块空间
- 一个程序的栈大小是有限的,如果一个数组特别大时,会导致栈溢出,所以不要在栈里面定义太大的数组,此时可以使用堆来存数据
- 如果一个数组的长度不能确定的时候,适合用堆而不是用栈存储数据
<num>
:空间大小,单位字节
1
| 数据类型 *变量名 = malloc(<num>);
|
自动变量
- 如果存储为自动变量,在手动释放后仍然可以使用,但是释放后再次使用时,是一个新的堆空间,而且使用完仍然需要手动释放。释放的不是变量,而是指针指向的堆内的空间
1
| auto 数据类型 *变量名 = malloc(<num>);
|
释放
在堆中开辟多块空间
- malloc只负责开辟空间,所以需要自己使用memset来清空数据
<num> * sizeof(int)
:一共开辟的空间大小
1
| int *变量名 = malloc(<num> * sizeof(int));
|
- calloc不仅负责开辟空间,还会进行数据的初始化
<num>
:开辟的空间个数
sizeof(int)
:每一块空间的大小
1
| int *变量名 = calloc(<num>, sizeof(int));
|
重新分配开辟的空间
- 使用malloc或calloc开辟的空间需要调整时,可以使用realloc
- realloc开辟的空间也需要手动清除数据
变量名
:想要修改空间的变量(返回的变量可以不相同,但通常设置为相同,因为旧的变量不需要自己维护)
1
| 变量名 = realloc(变量名, 新指定的内存大小);
|
最小堆内存单位
- Windows堆内存最小页为4k
- 所以如果从操作系统开辟1k空间,实际上操作系统会给4k空间,而再要时候,就不会再给空间,直到4k满了,再要1k空间时,操作系统再给4k空间
- 优点是操作系统效率更高,缺点是会浪费内存
完成