返回

动态内存管理:了解 malloc 家族和柔性数组,掌控 C 语言内存

后端

引言

在 C 语言编程中,理解动态内存管理至关重要,它赋予了我们分配和释放内存空间的灵活性,以满足程序的不断变化的需求。在本篇文章中,我们将深入探讨 malloc 家族中的动态内存分配函数,以及柔性数组如何扩展 C 语言中数组的用法。

malloc 家族

malloc 函数是 C 语言中用于动态分配内存空间的主要函数。它接受一个参数,指定要分配的字节数,并返回指向已分配内存块起始地址的指针。malloc 函数的原型如下:

void *malloc(size_t size);

在分配完内存后,可以通过 free 函数释放该内存空间,以便操作系统可以将其重新用于其他目的。free 函数的原型如下:

void free(void *ptr);

realloc 函数用于重新分配先前分配的内存块。它接受两个参数:要重新分配的内存块的指针和新的请求大小。realloc 函数会返回一个指向新分配的内存块起始地址的指针。realloc 函数的原型如下:

void *realloc(void *ptr, size_t size);

calloc 函数是 malloc 函数的变体,它在分配内存块时会将其初始化为零。calloc 函数的原型如下:

void *calloc(size_t num, size_t size);

柔性数组

C99 标准引入了柔性数组,又称可变长数组。柔性数组允许我们在不指定确切大小的情况下声明数组。柔性数组的声明语法如下:

struct array_name {
    int len;
    type member_name[];
};

在上面的声明中,len 表示数组中元素的数量,member_name 是数组中元素的类型。柔性数组必须是结构体的一部分。

例如,以下代码声明了一个柔性数组,其中包含 10 个整数元素:

struct my_array {
    int len;
    int members[];
};

struct my_array arr = {10, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}};

使用 malloc 家族和柔性数组

让我们通过一个示例来说明如何在 C 语言中使用 malloc 家族和柔性数组。我们创建一个动态通讯录程序,允许用户添加和删除联系人。

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

struct contact {
    char name[50];
    char phone_number[20];
    char email[50];
};

int main() {
    // 使用 malloc 为通讯录分配内存
    struct contact *contacts = malloc(sizeof(struct contact));

    // 使用 realloc 为通讯录重新分配内存以添加新联系人
    contacts = realloc(contacts, sizeof(struct contact) * (contacts->len + 1));

    // 使用 calloc 为新联系人分配内存
    struct contact *new_contact = calloc(1, sizeof(struct contact));

    // 读取新联系人的详细信息
    printf("Enter contact name: ");
    scanf("%s", new_contact->name);

    printf("Enter contact phone number: ");
    scanf("%s", new_contact->phone_number);

    printf("Enter contact email: ");
    scanf("%s", new_contact->email);

    // 将新联系人添加到通讯录
    contacts[contacts->len++] = *new_contact;

    // 释放新联系人的内存
    free(new_contact);

    // 打印通讯录
    for (int i = 0; i < contacts->len; i++) {
        printf("Contact %d:\n", i + 1);
        printf("Name: %s\n", contacts[i].name);
        printf("Phone number: %s\n", contacts[i].phone_number);
        printf("Email: %s\n\n", contacts[i].email);
    }

    // 释放通讯录的内存
    free(contacts);

    return 0;
}

结论

理解动态内存管理对于 C 语言程序员至关重要。malloc 家族中的函数和柔性数组提供了强大的工具,使我们能够根据需要灵活地分配和释放内存空间。掌握这些技术将使您能够编写出更高效、更健壮的 C 语言代码。