C语言realloc函数使用注意事项

今天在练习动态数组的增删差改,看过视频课程觉得还算简单,但实际写代码过程中发现了各种各样的问题,错误最多出现在realloc函数的使用,但在不断的出错改正过程中,也提升了对realloc函数的理解。于是重新梳理了realloc函数的定义和使用方式。

🧱 一、realloc 函数原型

void* realloc(void* ptr, size_t new_size);
  • ptr:之前 malloccalloc 或 realloc 返回的指针(可以是 NULL
  • new_size新的总大小(以字节为单位)
  • 返回值:成功返回新地址,失败返回 NULL

🔥 核心:realloc 是“重新分配”,不是“增加”!


⚠️ 二、realloc 的 7 大注意事项(必看!)


❌ 注意事项 1:不能假设 realloc 返回原地

// ❌ 错误!
realloc(ptr, new_size);
// ptr 可能已失效!
// ✅ 正确:用临时指针接收
void* temp = realloc(ptr, new_size);
if (temp == NULL) {
    // 处理失败,ptr 仍有效
    return;
}
ptr = temp; // 成功后才更新

🔥 为什么? realloc 可能无法在原地扩展,会分配新内存并复制数据,返回新地址。


❌ 注意事项 2:realloc 失败时返回 NULL,但原内存仍有效

// ❌ 危险!
ptr = realloc(ptr, new_size);
if (ptr == NULL) {
    // 此时 ptr 已被覆盖为 NULL,原内存丢失!→ 内存泄漏!
}
// ✅ 安全做法
void* temp = realloc(ptr, new_size);
if (temp == NULL) {
    // 处理错误,但 ptr 仍指向原内存,可继续使用或释放
    perror("realloc failed");
    return ptr; // 或返回错误
}
ptr = temp; // 仅在成功时更新

🔥 黄金法则:永远用临时指针接收 realloc 结果!


❌ 注意事项 3:不要对栈内存或未动态分配的内存使用 realloc

int arr[10];
realloc(arr, 20 * sizeof(int)); // ❌ 未定义行为!崩溃!

int* ptr = malloc(10 * sizeof(int));
free(ptr);
realloc(ptr, 20 * sizeof(int)); // ❌ 已释放的内存,未定义行为!

🔥 realloc 只能用于 malloc/calloc/realloc 返回的指针。


❌ 注意事项 4:new_size 是“总大小”,不是“增加的大小”

// ❌ 错误理解:以为是“增加一个 int”
realloc(arr, sizeof(int));
// ✅ 正确:new_size 是总字节数
int new_length = old_length + 1;
void* temp = realloc(arr, new_length * sizeof(int));

❌ 注意事项 5:realloc 可能“原地扩展”

如果当前内存块后面有足够空闲空间,realloc 可能直接扩展它,不移动数据,返回原地址

ptr = malloc(100);
ptr2 = realloc(ptr, 200); // 可能 ptr2 == ptr

🔥 这是 realloc 的优化机制,返回相同地址不等于失败


❌ 注意事项 6:realloc(ptr, 0) 的行为是实现定义的

realloc(ptr, 0); // 可能等价于 free(ptr),也可能返回特殊指针

🔥 不要依赖 realloc(ptr, 0),想释放内存就用 free(ptr)


❌ 注意事项 7:realloc(NULL, size) 等价于 malloc(size)

int* arr = realloc(NULL, 10 * sizeof(int)); // 等价于 malloc(10 * sizeof(int))

🔥 这是一个有用的技巧,可以统一内存分配逻辑。


🔄 三、realloc 的底层行为(图解)

假设内存布局如下:

[ 已用 ][ 空闲 ][ 其他 ]
  • 如果 空闲 足够:realloc 直接扩展,不复制数据
  • 如果 空闲 不够:realloc 分配新块,复制数据,释放旧块

👉 所以 realloc 可能快(原地扩展),也可能慢(搬家复制)


✅ 四、安全使用 realloc 的模板(收藏!)

int* safe_realloc(int* ptr, int old_size, int new_size) {
    void* temp = realloc(ptr, new_size * sizeof(int));
    if (temp == NULL) {
        perror("realloc failed");
        // 可以选择:返回原指针,或报错退出
        return ptr; // 或返回 NULL 并处理
    }
    return (int*)temp; // 成功,返回新指针
}

// 使用:
arr = safe_realloc(arr, old_length, new_length);

🎯 五、性能优化:为什么用“2 倍扩容”?

策略平均插入时间总时间
每次 +1O(n)O(n²)
2 倍扩容O(1) 摊销O(n)

🔥 摊销分析:虽然某次 realloc 很慢,但平均下来每次插入只花常数时间。


🧩 六、常见错误代码对比

错误写法正确写法
ptr = realloc(ptr, size);temp = realloc(ptr, size); if (temp) ptr = temp;
realloc(ptr, size);ptr = realloc(ptr, size);(且检查 NULL)
realloc(ptr, sizeof(int))realloc(ptr, new_count * sizeof(int))

✅ 七、总结:realloc 使用口诀

🔥 “一临二查三更新,大小总值莫弄混;
NULL 不放原内存,倍增扩容最划算。”

口诀解释
一临用临时指针接收
二查检查临时指针是否为 NULL
三更新成功后再更新原指针
大小总值new_size 是总大小,不是增量
NULL 不放realloc 失败时原内存仍有效
倍增扩容用 2 倍策略摊销性能
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值