027. 使用动态内存分配

在C语言中,动态内存分配允许程序在运行时请求和释放内存。这与静态内存分配(在编译时分配)不同,动态内存分配提供了更大的灵活性,尤其是在处理不确定大小的数据结构(如数组、链表等)时。C语言提供了几个标准库函数来管理动态内存分配,主要包括malloccallocreallocfree

1. malloc函数

malloc用于分配指定大小的内存块。分配的内存未初始化,其内容是未定义的。

函数原型

void *malloc(size_t size);
  • size:要分配的字节数。

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

示例1:使用malloc分配内存

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

int main() {
    int *ptr = (int *)malloc(5 * sizeof(int)); // 分配5个整数的内存
    if (ptr == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }

    // 初始化并打印数组
    for (int i = 0; i < 5; i++) {
        ptr[i] = i + 1;
        printf("%d ", ptr[i]);
    }
    printf("\n");

    // 释放内存
    free(ptr);
    printf("Memory freed\n");

    return 0;
}

输出结果

1 2 3 4 5 
Memory freed

2. calloc函数

calloc用于分配内存,并将内存初始化为零。它通常用于分配数组。

函数原型

void *calloc(size_t num, size_t size);
  • num:要分配的元素数量。

  • size:每个元素的大小(以字节为单位)。

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

示例2:使用calloc分配并初始化内存

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

int main() {
    int *ptr = (int *)calloc(5, sizeof(int)); // 分配5个整数的内存并初始化为0
    if (ptr == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }

    // 打印数组
    for (int i = 0; i < 5; i++) {
        printf("%d ", ptr[i]);
    }
    printf("\n");

    // 释放内存
    free(ptr);
    printf("Memory freed\n");

    return 0;
}

输出结果

0 0 0 0 0 
Memory freed

3. realloc函数

realloc用于调整已分配内存块的大小。如果新大小大于原大小,新增部分的内容未定义;如果新大小小于原大小,超出部分的内容将被丢弃。

函数原型

void *realloc(void *ptr, size_t size);
  • ptr:指向原内存块的指针。

  • size:新的大小(以字节为单位)。

  • 返回值:成功时返回指向调整大小后的内存块的指针,失败时返回NULL

示例3:使用realloc调整内存大小

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

int main() {
    int *ptr = (int *)malloc(5 * sizeof(int)); // 分配5个整数的内存
    if (ptr == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }

    // 初始化并打印数组
    for (int i = 0; i < 5; i++) {
        ptr[i] = i + 1;
        printf("%d ", ptr[i]);
    }
    printf("\n");

    // 调整内存大小到10个整数
    int *newPtr = (int *)realloc(ptr, 10 * sizeof(int));
    if (newPtr == NULL) {
        printf("Memory reallocation failed\n");
        free(ptr); // 释放原内存
        return 1;
    }
    ptr = newPtr;

    // 初始化新分配的内存并打印数组
    for (int i = 5; i < 10; i++) {
        ptr[i] = i + 1;
        printf("%d ", ptr[i]);
    }
    printf("\n");

    // 释放内存
    free(ptr);
    printf("Memory freed\n");

    return 0;
}

输出结果

1 2 3 4 5 
6 7 8 9 10 
Memory freed

4. free函数

free用于释放之前分配的内存。

函数原型

void free(void *ptr);
  • ptr:指向要释放的内存块的指针。

示例4:释放动态分配的内存

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

int main() {
    int *ptr = (int *)malloc(5 * sizeof(int)); // 分配5个整数的内存
    if (ptr == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }

    // 初始化并打印数组
    for (int i = 0; i < 5; i++) {
        ptr[i] = i + 1;
        printf("%d ", ptr[i]);
    }
    printf("\n");

    // 释放内存
    free(ptr);
    printf("Memory freed\n");

    return 0;
}

输出结果

1 2 3 4 5 
Memory freed

5. 注意事项

  1. 内存泄漏:如果分配的内存没有被释放,会导致内存泄漏。确保在不再需要动态分配的内存时调用free
  2. 重复释放:不要多次释放同一块内存,这可能导致未定义行为。
  3. realloc失败:如果realloc失败,原内存块仍然有效,不会被释放。因此,在使用realloc时,应先将返回值赋给一个临时指针,检查是否为NULL,然后再更新原指针。
  4. 初始化malloc分配的内存在使用前应初始化,calloc会自动初始化为零。

通过上述示例,你可以看到如何在C语言中使用动态内存分配:

  1. malloc:分配未初始化的内存。
  2. calloc:分配并初始化为零的内存。
  3. realloc:调整已分配内存的大小。
  4. free:释放动态分配的内存。

视频讲解

BiliBili: 视睿网络-哔哩哔哩视频 (bilibili.com)