c语言 内存管理(malloc, calloc, free)

在C语言中,内存管理是一个核心概念,因为C让程序员直接控制内存的分配和释放。以下是 malloccallocfree 的详细说明:

1. malloc - 内存分配

功能:

分配指定字节数的内存块,不初始化内存内容。

语法:

cpp 复制代码
void* malloc(size_t size);

示例:

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

int main() {
    // 分配一个整数的内存
    int *ptr = (int*)malloc(sizeof(int));
    if (ptr == NULL) {
        printf("内存分配失败\n");
        return 1;
    }
    
    *ptr = 100;
    printf("值: %d\n", *ptr);
    
    free(ptr); // 释放内存
    return 0;
}

2. calloc - 分配并初始化内存

功能:

分配指定数量和大小的内存块,并将所有位初始化为0。

语法:

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

示例:

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

int main() {
    // 分配5个整数的数组,全部初始化为0
    int *arr = (int*)calloc(5, sizeof(int));
    if (arr == NULL) {
        printf("内存分配失败\n");
        return 1;
    }
    
    for(int i = 0; i < 5; i++) {
        printf("arr[%d] = %d\n", i, arr[i]); // 全部为0
    }
    
    free(arr);
    return 0;
}

3. free - 释放内存

功能:

释放之前分配的内存块。

语法

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

重要规则:

  • 只能释放通过 malloccallocrealloc 分配的内存

  • 不能重复释放同一块内存

  • 释放后应将指针设为NULL

综合示例

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

int main() {
    int n, i;
    
    printf("输入数组大小: ");
    scanf("%d", &n);
    
    // 使用malloc分配内存
    int *arr1 = (int*)malloc(n * sizeof(int));
    if(arr1 == NULL) {
        printf("内存分配失败!\n");
        return 1;
    }
    
    printf("malloc分配的内容(未初始化):\n");
    for(i = 0; i < n; i++) {
        printf("%d ", arr1[i]); // 可能是随机值
    }
    printf("\n");
    
    // 使用calloc分配内存
    int *arr2 = (int*)calloc(n, sizeof(int));
    if(arr2 == NULL) {
        printf("内存分配失败!\n");
        free(arr1);
        return 1;
    }
    
    printf("calloc分配的内容(初始化为0):\n");
    for(i = 0; i < n; i++) {
        printf("%d ", arr2[i]); // 全部为0
    }
    printf("\n");
    
    // 重新分配内存 (realloc)
    int *arr3 = (int*)realloc(arr2, 2 * n * sizeof(int));
    if(arr3 == NULL) {
        printf("内存重新分配失败!\n");
        free(arr1);
        free(arr2);
        return 1;
    }
    
    printf("重新分配后的数组:\n");
    for(i = 0; i < 2 * n; i++) {
        printf("%d ", arr3[i]);
    }
    printf("\n");
    
    // 释放所有内存
    free(arr1);
    free(arr3);
    
    // 将指针设为NULL避免悬空指针
    arr1 = NULL;
    arr3 = NULL;
    
    return 0;
}

最佳实践和注意事项

1. 总是检查返回值

cpp 复制代码
int *ptr = (int*)malloc(sizeof(int));
if (ptr == NULL) {
    // 处理分配失败的情况
}

2. 避免内存泄漏

cpp 复制代码
// 错误示例
void leak_memory() {
    int *ptr = (int*)malloc(100 * sizeof(int));
    // 忘记调用 free(ptr)
}

// 正确示例
void no_leak() {
    int *ptr = (int*)malloc(100 * sizeof(int));
    if (ptr != NULL) {
        // 使用内存
        // ...
        free(ptr); // 及时释放
        ptr = NULL; // 避免悬空指针
    }
}

3. 不要重复释放

cpp 复制代码
int *ptr = (int*)malloc(sizeof(int));
free(ptr);
// free(ptr); // 错误!重复释放

4. 动态数组示例

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

int main() {
    int size;
    printf("输入数组大小: ");
    scanf("%d", &size);
    
    // 动态分配数组
    double *scores = (double*)malloc(size * sizeof(double));
    if (scores == NULL) {
        printf("内存分配失败\n");
        return 1;
    }
    
    // 输入数据
    for (int i = 0; i < size; i++) {
        printf("输入分数 %d: ", i + 1);
        scanf("%lf", &scores[i]);
    }
    
    // 计算平均值
    double sum = 0;
    for (int i = 0; i < size; i++) {
        sum += scores[i];
    }
    printf("平均分: %.2f\n", sum / size);
    
    free(scores);
    return 0;
}

alloc vs calloc 对比

特性 malloc calloc
初始化 不初始化 初始化为0
参数 一个参数(总字节数) 两个参数(元素个数, 元素大小)
性能 稍快 稍慢(因为要初始化)
使用场景 需要手动初始化时 需要零初始化时

掌握这些内存管理函数对于编写高效、稳定的C程序至关重要。

相关推荐
小此方2 小时前
「C++AI大模型接入SDK」(一) API接入与本地两种方式对比、API Key获取、API报文详解与简单API的构建
开发语言·c++·人工智能
wuyk5552 小时前
Python实战项目02:学生成绩管理系统(控制台|CSV导出|完整落地)
开发语言·python
浪子明X9 小时前
十六位账本怎样发现传输差错:Internet Checksum 生活类比
开发语言
xiangyun6112 小时前
【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清
c语言·开发语言·数据结构·c++·算法
xiangyun6112 小时前
【408数据结构 06】双链表、循环链表、静态链表
c语言·开发语言·数据结构·c++·算法
白远山13 小时前
家政服务家政社区派单实战:调度系统架构设计与实现指南
java·开发语言·小程序·架构·需求分析
Logic10114 小时前
C语言/数据结构数组题解:数字列表加一(Plus One)——进位处理与数组扩展
c语言·数据结构·模拟·数组·时间复杂度·算法题·进位
Escalating_xu14 小时前
【C语言常见概念】从第一行代码到字符串结束标志:一次打通编译、main、ASCII、转义字符与注释
c语言·c++
DevRay14 小时前
Java 21虚拟线程深度实战:告别线程池焦虑,百万并发吞吐量直接翻倍(原理+代码+避坑)
java·开发语言
Navigator_Z14 小时前
LeetCode //C - 1250. Check If It Is a Good Array
c语言·算法·leetcode