C 语言 动态内存分配

一、核心作用

普通数组大小必须编译期确定;

动态内存可以程序运行时申请内存,堆(heap)上分配,用完手动释放。

bash 复制代码
头文件:<stdlib.h>

二、4 个核心函数

1. malloc

• 功能:分配size 字节连续内存,不初始化,内容随机垃圾值

• 返回:成功→内存首地址;失败→NULL

bash 复制代码
// 分配能存5个int的空间
int *p = (int *)malloc(5 * sizeof(int));
if(p == NULL)

{

    // 必须判空!
    perror("malloc fail");
    return -1;
}

2. calloc

复制代码
void *calloc(size_t num, size_t size);

• 功能:分配num个、每个size字节的内存,自动初始化为 0

bash 复制代码
int *p = (int *)calloc(5, sizeof(int));

3. realloc 重新调整大小

复制代码
void *realloc(void *ptr, size_t new_size);

• 扩容 / 缩容已有动态内存

• 注意:

  1. 不要直接 p = realloc(p, ...),失败会返回 NULL,丢失原地址造成内存泄漏

  2. 扩容不一定原地,可能拷贝数据到新地址

bash 复制代码
int *tmp = realloc(p, 10 * sizeof(int));
if(tmp != NULL){
    p = tmp;
}

4. free 释放内存

bash 复制代码
void free(void *ptr);

• 归还堆内存,必须配对使用

• 规则:

  • free 只能释放 malloc/calloc/realloc 得到的指针
  • 不能重复 free、不能 free 栈上变量
  • free 之后指针变成野指针,建议手动置 NULL
bash 复制代码
free(p);
p = NULL;

三、完整示例

bash 复制代码
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int n = 5;
    // 堆区申请内存,不初始化
    int *arr = (int *)malloc(n * sizeof(int));

    // ⚠重点:必须判断分配是否成功
    if(arr == NULL){
        printf("malloc fault\n");
        return 1; // 异常退出
    }

    for(int i = 0; i < n; i++){
        arr[i] = i + 1;
    }

    // ⚠易错:realloc先用临时指针接收,失败不会覆盖原地址
    int *tmp = realloc(arr, 10 * sizeof(int));
    if(tmp == NULL)
    {
        printf("realloc fault\n");
        free(arr);
        arr = NULL;
        return 1;
    }
    arr = tmp;

    // ⚠扩容新增区域数据随机,如需使用要手动赋值

    free(arr);      // ⚠堆内存使用完必须释放
    arr = NULL;     // ⚠防止野指针

    return 0; // 正常退出
}

四、常见坑

  1. 忘记 free → 内存泄漏

  2. free 之后继续使用指针 → 野指针访问(程序崩溃)

  3. 重复 free 同一地址

  4. realloc 直接赋值原指针,分配失败丢失内存

  5. 不判断 malloc 返回 NULL,内存不足直接崩溃

  6. sizeof( )写错,大小分配不足造成越界

五、栈内存 vs 堆内存

区域 分配方式 释放 生命周期
栈 (stack) 局部数组、局部变量 函数结束自动回收 函数内有效
堆 (heap) malloc/calloc 手动 free 直到 free 或程序结束
相关推荐
光依旧11 分钟前
MCP实战手记系列(五):让工具返回一个能点的界面(文末附github源码链接)
java·spring ai·前端集成·mcp·mcp apps
APIshop17 分钟前
淘宝选品接口实战:从召回、详情、佣金到转链的 Java 接入笔记
java
雨落在了我的手上28 分钟前
Java数据结构(十四):Map和Set
数据结构
码行山野赴时序归途32 分钟前
链表家族收官篇:循环链表
c语言·开发语言·数据结构·链表
泡茶喝茶写代码32 分钟前
量化数据进阶:多维实战篇(第 11 篇):历史涨跌停价:涨跌停序列与止损线测算
java·python·股票数据api·股票数据·股票数据api接口·股票api数据接口·股票量化数据api
景熙55231 小时前
单体项目编写思路和落地形式
java·开发语言
Ivanqhz1 小时前
Slope One 算法详解:与矩阵分解、共现矩阵的异同
java·服务器·网络·人工智能·深度学习
别动我齐刘海1 小时前
ROS2 Jazzy + C++ 实战路线——进阶学习3
c++·人工智能·vscode·python·算法·机器学习·机器人
Bs_MoneyMagnet1 小时前
基于springboot+vue的非遗物质文化遗产系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
万物智能1 小时前
波形发生AD9833模块配置—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
java