一、C语言内存模型
| 内存区域 | 存储的内容 |
|---|---|
| 栈区(Stack) | 局部变量 |
| 堆区(Heap) | 动态分配的内存 |
| 静态区 | 全局变量、静态局部变量、字符串字面量常量 |
| 代码区 | 函数代码块 |
静态内存分配: 内存空间分配之后,大小不可以再调整。
动态内存分配: 内存空间分配之后,大小可以再调整。
二、void指针
- void 指针可以指向任何类型的数据。
- void 指针不可以被解引用。
(1)其他类型指针赋给 void指针,使用隐式转换即可,因为 void 指针不包含指向的数据类型的信息,通常是安全的。
(2)void 指针赋给其他类型指针,建议使用显式类型转换,这样更加安全,如果使用隐式类型转换,有些编译器会触发警告。
三、内存分配函数
1.malloc
malloc用于分配一块连续的内存空间。
void *malloc(size_t size);
- size表示分配的字节数。
- 如果分配失败,则返回NULL。
2.calloc
calloc用于分配一块连续的内存空间,并初始化数据为0。
void *calloc(size_t numElements, size_t sizeOfElement);
- 第一个参数表示多少个元素个数。
- 第二个参数表示每个元素的字节数。
- 如果分配失败,则返回NULL。
3.realloc
realloc用于重新分配一个动态分配的内存空间大小,并复制原来的数据。
void *realloc(void *ptr, size_t size);
- 第一个参数表示需要重新分配的地址。
- 第二个参数表示新内存空间大小。
- 如果分配失败,则返回NULL。
4.free
free用于释放动态分配的内存。
void free(void *ptr);
- ptr表示需要释放的动态分配的地址。
- 忘记释放的动态内存,会造成内存泄漏。
5.内存分配原则
- 避免分配大量的小内存块。分配堆上的内存有一些系统开销,所以分配许多小的内存块比分配几个大内存块的系统开销大。
- 仅在需要时分配内存。只要使用完堆上的内存块,就需要及时释放它,否则可能出现内存泄漏。
- 总是确保释放已分配的内存。在编写分配内存的代码时,就要确定好在代码的什么地方释放内存。