亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> C语言

malloc 与 calloc 深度对比:C 语言动态内存分配核心差异与实战指南

动态内存分配概述

动态内存分配允许程序在运行时按需申请和释放内存。C 标准库在 <stdlib.h> 中提供四大核心函数:malloc()、calloc()、realloc()、free(),分别对应分配、零初始化分配、重分配、释放。

malloc():分配单块未初始化内存

malloc()(memory allocation)按字节分配一块连续内存,返回指向首字节的 void* 指针。新分配的内存内容不确定(垃圾值),包含该物理位置原有的比特模式。

典型用法

int *p = (int *)malloc(n * sizeof(int));

分配失败返回 NULL。

calloc():分配并零初始化多块内存

calloc()(contiguous allocation)接受两个参数:元素个数 num 与单个元素大小 size。它分配 num * size 字节,并自动将每个字节置零,适合需要“干净起始状态”的数组或结构体。

典型用法

int *p = (int *)calloc(n, sizeof(int));

分配失败同样返回 NULL。

何时选择哪个?

函数原型

malloc()

void *malloc(size_t size);

calloc()

void *calloc(size_t num, size_t size);

实战代码示例

示例 1:malloc() 存储 15 个整数

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

int main(void) {
    int *ptr = malloc(15 * sizeof(*ptr));   // 使用 sizeof(*ptr) 便于类型变更
    if (!ptr) {
        perror("malloc failed");
        return EXIT_FAILURE;
    }
    ptr[5] = 480;                           // 第 6 个元素(下标 5)
    printf("Value of the 6th integer is %d\n", ptr[5]);
    free(ptr);                              // 释放内存
    return EXIT_SUCCESS;
}

输出: Value of the 6th integer is 480

示例 2:calloc() 计算前 10 项和

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

int main(void) {
    int *ptr = calloc(10, sizeof(int));     // 自动清零
    if (!ptr) {
        perror("calloc failed");
        return EXIT_FAILURE;
    }
    int sum = 0;
    for (int i = 0; i < 10; ++i) {
        ptr[i] = i;                         // 显式赋值(虽然后赋值覆盖了零值)
        sum += ptr[i];
    }
    printf("Sum = %d\n", sum);
    free(ptr);
    return EXIT_SUCCESS;
}

输出: Sum = 45

核心差异对比表

特性malloc()calloc()
参数个数1 个(总字节数)2 个(元素数、单元大小)
分配后内存状态未初始化(垃圾值)全零初始化
典型用例单块内存、自行初始化数组/结构体需清零起始
性能略快(无清零)稍慢(清零开销)
安全性读未初始化值风险高自动清零降低风险
失败返回值NULLNULL
所需头文件stdlib.hstdlib.h
溢出保护手工检查 n * size 溢出内部计算 num * size,部分实现含溢出检查

深度洞察:calloc 的隐藏性能优势

现代操作系统(Linux、Windows、macOS)维护零页:当 calloc 请求大块内存时,内核可直接映射只读零页,并通过写时复制延迟物理内存分配。这使得 calloc 在大块分配时往往比 malloc + memset 更快、内存占用更低(直到真正写入)。

关键要点总结

常见错误对照表

错误代码问题修正
int *p = malloc(10);仅分配 10 字节,非 10 个 intmalloc(10 * sizeof(int))
int *p = calloc(sizeof(int), 10);参数顺序反了calloc(10, sizeof(int))
free(ptr); ptr[0]=1;释放后继续使用(UAF)释放后置 ptr = NULL
ptr = malloc(n); ... ptr = malloc(m);覆盖指针导致首块泄漏先 free(ptr) 再重新分配

C语言

  1. 用复数演示交流电压叠加:三电源串联案例
  2. C# 表达式、语句与代码块:全面指南与实战示例
  3. C++ do-while 循环详解:语法、实战示例与嵌套循环
  4. C++ 指针精通:核心概念、代码示例与实战应用
  5. C++ char 类型完全指南:声明、ASCII 码、输入输出与字符串转换
  6. C++ 运算符重载实战指南:语法、方法、限制与代码示例
  7. C++ 函数详解:从声明到调用的实战指南
  8. C# 集合实战教程:ArrayList、Stack、Queue、Hashtable 等核心类型全解析
  9. while 与 do-while 循环深度对比:原理、语法与实战案例全解析
  10. C 语言 calloc() 详解:零初始化动态分配原理与实战案例
  11. Python str.count() 完全指南:统计字符与子串出现次数实战
  12. Python round() 函数详解与实战示例