动态内存管理

1. malloc

在这里插入图片描述
用于开辟一段连续的内存空间。

  • 如果开辟成功就返回指向该空间的指针,如果失败则返回空指针
  • malloc不知道开辟空间的类型,需要手动设置
  • 如果size是0,标准是未定义的,取决于编译器
  • 不会初始化
#include <stdio.h>
#include <stdlib.h>

int main() {
    // 分配能存储 5 个 int 类型元素的内存(假设 int 为 4 字节,共 20 字节)
    int* arr = (int*)malloc(5 * sizeof(int));
    
    // 检查内存分配是否成功
    if (arr == NULL) {
        printf("内存分配失败\n");
        return 1; // 退出程序
    }
    
    // 使用内存(需手动初始化)
    for (int i = 0; i < 5; i++) {
        arr[i] = i + 1; // 手动赋值
        printf("%d ", arr[i]); // 输出:1 2 3 4 5
    }
    
    // 释放内存(必须执行,否则内存泄漏)
    free(arr);
    arr = NULL; // 避免悬垂指针(指向已释放的内存)
    return 0;
}

2. calloc

在这里插入图片描述
为num个大小为size的元素开辟空间

  • 与malloc不同的是,calloc会将空间中的元素初始化为0
  • 其他的和malloc一致
#include <stdio.h>
#include <stdlib.h>

int main() {
    // 分配 5 个 int 类型的元素,自动初始化为 0
    int* arr = (int*)calloc(5, sizeof(int));
    
    if (arr == NULL) {
        printf("内存分配失败\n");
        return 1;
    }
    
    // 验证初始值(均为 0)
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]); // 输出:0 0 0 0 0
    }
    
    // 使用内存(重新赋值)
    for (int i = 0; i < 5; i++) {
        arr[i] = i * 2;
    }
    
    free(arr);
    arr = NULL;
    return 0;
}

3. realloc

在这里插入图片描述
realloc可以给已经存在的一段空间重新分配大小,将指向目标空间的指针作为参数再设置想要的大小即可。返回值为调整之后的空间的起始位置
realloc的调整分为两种情况
1.原有空间之后有足够大的位置
在这里插入图片描述

2.原有空间后没有足够大的位置
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>

int main() {
    // 先用 malloc 分配 3 个 int 的内存
    int* arr = (int*)malloc(3 * sizeof(int));
    if (arr == NULL) {
        printf("初始分配失败\n");
        return 1;
    }
    
    // 初始化数据
    for (int i = 0; i < 3; i++) {
        arr[i] = i;
    }
    
    // 用 realloc 扩展为 5 个 int 的内存
    int* new_arr = (int*)realloc(arr, 5 * sizeof(int));
    if (new_arr == NULL) {
        printf("重新分配失败,原内存保持不变\n");
        free(arr); // 仍需释放原内存
        return 1;
    }
    arr = new_arr; // 更新指针(指向新内存块)
    
    // 赋值新增的元素
    arr[3] = 3;
    arr[4] = 4;
    
    // 输出所有元素
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]); // 输出:0 1 2 3 4
    }
    
    free(arr);
    arr = NULL;
    return 0;
}

4. 三者的核心区别

在这里插入图片描述

5. free

释放掉开辟的空间,最好是手动释放,否则可能出问题。

6. 常见错误

  1. 对空指针的解引⽤操作
  2. 对动态开辟空间的越界访问
int main()
{
	int i = 0;
	int* p = (int*)malloc(10 * sizeof(int));
	for (i = 0; i <= 10; i++)
	{}// 越界
	free(p);

	return 0;
}
  1. 对⾮动态开辟内存使⽤free释放
int main()
{
	int a = 10;
	int* p = &a;
	free(p);

	return 0;
}
  1. 使⽤free释放⼀块动态开辟内存的⼀部分
int main()
{
	int* p = (int*)malloc(40);
	*p++;//不再指向起始位置
	free(p);

	return 0;
}
  1. 对同⼀块动态内存多次释放
  2. 动态开辟内存忘记释放(内存泄漏)

7. 程序内存区域划分

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值