c语言系列——malloc、calloc、realloc三者的区别

c语言系列——malloc、calloc、realloc三者的区别

在 C 语言中,malloccallocrealloc 都是用于动态内存分配的标准库函数(声明在 stdlib.h 中),但它们在参数、初始化方式、功能场景上有显著区别。以下是三者的核心差异及适用场景:

一、函数原型与基本功能

函数原型核心功能
mallocvoid* malloc(size_t size);分配一块大小为 size 字节的未初始化内存
callocvoid* calloc(size_t nmemb, size_t size);分配 nmemb 个、每个大小为 size 字节的内存块,并初始化为 0
reallocvoid* realloc(void* ptr, size_t size);调整已分配内存块(ptr 指向)的大小为 size 字节

二、核心区别详解

1. 参数与内存大小计算
  • malloc:仅需一个参数 size,表示要分配的总字节数(需手动计算总大小)。
    例:分配 10 个 int 类型的内存:malloc(10 * sizeof(int))
  • calloc:需要两个参数 nmemb(元素个数)和 size(单个元素大小),总分配大小为 nmemb * size 字节(自动计算总大小)。
    例:分配 10 个 int 类型的内存:calloc(10, sizeof(int))(等价于 malloc(10 * sizeof(int)),但初始化方式不同)。
  • realloc:需要两个参数 ptr(指向已分配内存的指针,由 malloc/calloc/realloc 返回)和 size(新的总字节数)。
    例:将之前分配的 10 个 int 内存调整为 20 个:realloc(ptr, 20 * sizeof(int))
2. 内存初始化
  • malloc不初始化内存,分配的内存中是随机的 “垃圾值”(可能是之前程序遗留的数据)。
    例:分配后直接访问,可能得到 0xcccccccc(调试模式下常见的未初始化标记)或其他随机值。
  • calloc会将分配的内存全部初始化为 0(二进制位全为 0)。
    例:分配后所有 int 元素的值都是 0,字符数组的每个元素都是 '\0'
  • realloc
    • 缩小内存:原内存中前 size 字节的数据保留,超出部分被截断(不初始化)。
    • 扩大内存
      • 若原内存块后有足够空间扩展,直接在原地扩展,新增部分是未初始化的垃圾值
      • 若原内存块后空间不足,会分配新内存块,将原数据复制到新块,新增部分是未初始化的垃圾值
3. 适用场景
  • malloc:适用于不需要初始化的内存分配(如临时缓冲区、存储中间结果),效率略高于 calloc(因省去清零步骤)。
  • calloc:适用于需要初始化为 0 的场景(如数组初始化、结构体清零、避免未初始化内存导致的逻辑错误)。
  • realloc:适用于动态调整内存大小的场景(如动态数组扩容、根据输入数据量实时调整缓冲区大小)。
4. 特殊行为
  • malloc(0):标准未定义具体行为,多数编译器会返回一个 “非 NULL 的空指针”(可安全释放,但不能访问)。
  • calloc(0, size)calloc(nmemb, 0):类似 malloc(0),返回可释放的空指针。
  • realloc(NULL, size):等价于 malloc(size)(重新分配一块新内存)。
  • realloc(ptr, 0):等价于 free(ptr) 并返回 NULL(释放原内存,不分配新内存)。

三、示例对比

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

int main() {
    // 1. malloc:分配未初始化内存
    int* m_ptr = (int*)malloc(3 * sizeof(int));
    printf("malloc 未初始化:%d, %d, %d\n", m_ptr[0], m_ptr[1], m_ptr[2]);  // 随机值

    // 2. calloc:分配并初始化为0
    int* c_ptr = (int*)calloc(3, sizeof(int));
    printf("calloc 初始化后:%d, %d, %d\n", c_ptr[0], c_ptr[1], c_ptr[2]);  // 0, 0, 0

    // 3. realloc:调整内存大小(将3个int扩为5个)
    int* r_ptr = (int*)realloc(c_ptr, 5 * sizeof(int));
    printf("realloc 扩展后(前3个保留,后2个未初始化):\n");
    printf("%d, %d, %d, %d, %d\n", r_ptr[0], r_ptr[1], r_ptr[2], r_ptr[3], r_ptr[4]);

    // 释放内存
    free(m_ptr);
    free(r_ptr);  // 注意:realloc后原c_ptr已失效,只需释放新指针
    return 0;
}

可能的输出(后两个值为随机垃圾值):

malloc 未初始化:-1217433232, 32766, -1216345424
calloc 初始化后:0, 0, 0
realloc 扩展后(前3个保留,后2个未初始化):
0, 0, 0, -1217433232, 32766

四、总结

维度malloccallocrealloc
初始化不初始化(垃圾值)初始化为 0新增 / 缩小部分不初始化
参数总字节数 size元素数 nmemb + 单个大小 size原指针 ptr + 新总字节数 size
核心用途通用内存分配需要清零的内存分配调整已有内存块大小
效率略高(无清零操作)略低(需清零)取决于是否需要移动内存块

使用时需注意:三者返回的指针均需手动通过 free 释放(避免内存泄漏);分配失败时均返回 NULL,需检查返回值以避免空指针错误。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值