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程序至关重要。

相关推荐
歪歪1003 小时前
在C#中除了按属性排序,集合可视化器还有哪些辅助筛选的方法?
开发语言·前端·ide·c#·visual studio
degen_3 小时前
注册协议通知
c语言·笔记
李高钢4 小时前
c#获取当前程序所在目录避坑
开发语言·数据库·c#
IT北辰4 小时前
用 Python 实现连续数据分组求和并回写
开发语言·python
Yupureki4 小时前
从零开始的C++学习生活 19:C++复习课(5.4w字全解析)
c语言·数据结构·c++·学习·1024程序员节
凤山老林4 小时前
还在用JDK8?JDK8升级JDK11:一次价值千万的升级指南
java·开发语言·jvm·spring boot·后端·jdk
沐知全栈开发5 小时前
Servlet 数据库访问
开发语言
七夜zippoe5 小时前
Rust `std::iter` 深度解析:`Iterator` Trait、适配器与性能
开发语言·算法·rust
靠沿5 小时前
JavaSE知识分享——继承(下)
java·开发语言