2. malloc函数:函数原型、参数与返回值、基本用法

好,咱们正式开始聊动态内存分配。说实话,C语言里最让新手头疼的,就是这块内容。但你别怕,我带你一步步拆解。

先问个问题:为什么需要动态分配?你想想看,写程序时经常遇到这种情况——用户要输入多少数据,你事先根本不知道。比如写个学生成绩管理系统,有的班30人,有的班60人。你总不能每次都开个1000人的数组吧?太浪费了。这时候,malloc就派上用场了。

2.1 函数原型

malloc的全名是memory allocation,内存分配。它的原型长这样:

#include <stdlib.h>

void *malloc(size_t size);

嗯,这里有几个关键点,我一个个说。

2.2 参数:你要多大?

size参数,说白了就是你想要多少字节的内存。类型是size_t,通常是个无符号整数。你可能会问:那我怎么知道一个int占几个字节?用sizeof啊!

核心要点:永远不要写死数字。比如你要10个int,别写malloc(40),要写malloc(10 * sizeof(int))。为什么?因为不同平台int大小可能不一样。我当年刚入行时就吃过这个亏,代码在32位机上跑得好好的,移植到64位就崩了。

2.3 返回值:成功还是失败?

返回值类型是void *,也就是一个无类型指针。这意味着它可以指向任何类型的数据。但有个坑——

  • 成功:返回指向分配内存的指针
  • 失败:返回NULL

警告:一定要检查返回值!我曾经见过一个同事,写了半天的代码,结果因为malloc返回NULL没检查,程序直接段错误。排查了一下午才发现是内存不够了。记住:malloc不是100%成功的。

2.4 基本用法:三步走

用malloc其实就三步,我总结一下:

  1. 调用malloc,传入你需要的字节数
  2. 检查返回值,确保不是NULL
  3. 用完之后free掉,释放内存

来看个完整的例子:

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

int main() {
    int *arr;
    int n = 5;
    
    // 第一步:分配内存
    arr = (int *)malloc(n * sizeof(int));
    
    // 第二步:检查是否成功
    if (arr == NULL) {
        printf("内存分配失败!\n");
        return 1;
    }
    
    // 使用这块内存
    for (int i = 0; i < n; i++) {
        arr[i] = i * 10;
        printf("arr[%d] = %d\n", i, arr[i]);
    }
    
    // 第三步:释放内存
    free(arr);
    
    return 0;
}

小技巧:很多人纠结要不要强制类型转换。在C语言中,void *可以隐式转换为任何指针类型,所以(int *)这个转换其实可以省略。但我个人习惯加上,因为这样代码更清晰,别人一看就知道你要存什么类型的数据。

2.5 知识体系图

下面这张图,把malloc的核心逻辑串起来了。你看一遍,心里就有谱了:

malloc 函数核心逻辑 malloc(size) 参数:size_t size 返回值:void * 成功 → 返回有效指针 失败 → 返回 NULL 使用内存 → 最后 free() 检查错误 → 处理异常

2.6 常见误区

我见过太多人在malloc上栽跟头了。这里列几个最常见的:

误区 正确做法 为什么
不检查返回值 始终判断 if (ptr == NULL) 内存可能不够,不检查就是埋雷
忘记free 用完后立即free,并置NULL 内存泄漏,程序跑久了就崩
free后继续用 free后把指针置NULL 野指针,随时可能段错误
写死数字 sizeof 计算 跨平台兼容性,代码可读性

我曾经踩过的坑:有一次写网络服务器,处理大量并发连接。我图省事,每次分配内存后都不检查返回值。结果线上环境内存吃紧,malloc返回NULL,程序直接崩溃。从那以后,我写malloc必加检查,成了肌肉记忆。

2.7 小结

malloc其实不复杂。记住三点:参数传大小,返回值判空,用完要free。嗯,就这么简单。但越是简单的东西,越容易在细节上翻车。你写代码的时候,多留个心眼就好。


公众号:蓝海资料掘金营,微信deep3321