首页 > 系统相关 >C中如何使用动态内存分配来管理数据结构?

C中如何使用动态内存分配来管理数据结构?

时间:2025-01-03 16:32:22浏览次数:3  
标签:gt int NULL 内存 动态内存 printf array 数据结构 分配

在C语言中,动态内存分配是通过标准库中的几个关键函数来实现的,这些函数包括malloccallocreallocfree。动态内存分配允许程序在运行时根据需要分配和释放内存,这对于处理大小不确定的数据结构(如链表、树等)尤为重要。下面将详细介绍这些函数的使用方法,并给出示例代码。

动态内存分配函数

  1. malloc

    • 「功能」:在堆上分配指定大小的内存块,并返回指向该内存块的指针。
    • 「原型」void*malloc(size_t size);
    • 「参数」size为需要分配的内存字节数。
    • 「返回值」:成功时返回指向分配内存的指针;失败时返回NULL
    • 「注意事项」:分配的内存未初始化,使用前需手动初始化。
  2. calloc

    • 「功能」:在堆上分配指定数量和大小的连续内存块,并将每个字节初始化为0。
    • 「原型」void*calloc(size_t num, size_t size);
    • 「参数」num为需要分配的元素数量,size为每个元素的大小。
    • 「返回值」:成功时返回指向分配内存的指针;失败时返回NULL
    • 「注意事项」:分配的内存已初始化为0,适合用于需要初始化的场景。
  3. realloc

    • 「功能」:调整已分配内存块的大小,可以增加或减少内存大小。
    • 「原型」void*realloc(void *ptr, size_t size);
    • 「参数」ptr为指向已分配内存块的指针,size为新的内存大小。
    • 「返回值」:成功时返回指向调整后内存块的指针;失败时返回NULL,原内存块不变。
    • 「注意事项」:如果新的内存大小为0,则相当于调用free(ptr);如果分配失败,原内存块不会被释放,需手动处理。
  4. free

    • 「功能」:释放之前通过malloccallocrealloc分配的内存块。
    • 「原型」void free(void*ptr);
    • 「参数」ptr为指向已分配内存块的指针。
    • 「返回值」:无返回值。
    • 「注意事项」:释放后指针应置为NULL,避免悬空指针。

示例代码

示例1:动态分配数组
#include <stdio.h>

#include <stdlib.h>



int main() {

    int n;

    printf("请输入数组的大小: ");

    scanf("%d", &n);



    // 动态分配内存

    int *array = (int*)malloc(n * sizeof(int));

    if (array == NULL) {

        printf("内存分配失败\n");

        return EXIT_FAILURE;

    }



    // 初始化数组

    for (int i = 0; i < n; i++) {

        array[i] = i + 1;

    }



    // 打印数组

    printf("数组元素: ");

    for (int i = 0; i < n; i++) {

        printf("%d ", array[i]);

    }

    printf("\n");



    // 释放内存

    free(array);

    array = NULL; // 避免悬空指针



    return EXIT_SUCCESS;

}

示例2:动态调整数组大小
#include <stdio.h>

#include <stdlib.h>



int main() {

    int n = 5;

    // 动态分配内存

    int *array = (int*)malloc(n * sizeof(int));

    if (array == NULL) {

        printf("内存分配失败\n");

        return EXIT_FAILURE;

    }



    // 初始化数组

    for (int i = 0; i < n; i++) {

        array[i] = i + 1;

    }



    // 打印数组

    printf("原始数组元素: ");

    for (int i = 0; i < n; i++) {

        printf("%d ", array[i]);

    }

    printf("\n");



    // 调整数组大小

    int new_size = 10;

    int *new_array = (int*)realloc(array, new_size * sizeof(int));

    if (new_array == NULL) {

        printf("内存调整失败\n");

        free(array);

        return EXIT_FAILURE;

    }

    array = new_array;



    // 初始化新增元素

    for (int i = n; i < new_size; i++) {

        array[i] = i + 1;

    }



    // 打印调整后的数组

    printf("调整后的数组元素: ");

    for (int i = 0; i < new_size; i++) {

        printf("%d ", array[i]);

    }

    printf("\n");



    // 释放内存

    free(array);

    array = NULL; // 避免悬空指针



    return EXIT_SUCCESS;

}

示例3:动态分配结构体
#include <stdio.h>

#include <stdlib.h>



// 定义结构体

struct Point {

    int x;

    int y;

};



void printPoint(struct Point *p) {

    printf("Point: (%d, %d)\n", p->x, p->y);

}



int main() {

    // 动态分配结构体

    struct Point *p = (struct Point*)malloc(sizeof(struct Point));

    if (p == NULL) {

        printf("内存分配失败\n");

        return EXIT_FAILURE;

    }



    // 初始化结构体

    p->x = 10;

    p->y = 20;



    // 打印结构体

    printPoint(p);



    // 释放内存

    free(p);

    p = NULL; // 避免悬空指针



    return EXIT_SUCCESS;

}

示例4:动态分配链表
#include <stdio.h>

#include <stdlib.h>



// 定义链表节点结构体

typedef struct Node {

    int data;

    struct Node *next;

} Node;



// 创建新节点

Node *newNode(int value) {

    Node *node = (Node*)malloc(sizeof(Node));

    if (node == NULL) {

        printf("内存分配失败\n");

        exit(EXIT_FAILURE);

    }

    node->data = value;

    node->next = NULL;

    return node;

}



// 打印链表

void printList(Node *head) {

    Node *current = head;

    while (current != NULL) {

        printf("%d -> ", current->data);

        current = current->next;

    }

    printf("NULL\n");

}



// 释放链表

void freeList(Node *head) {

    Node *current = head;

    while (current != NULL) {

        Node *next = current->next;

        free(current);

        current = next;

    }

}



int main() {

    // 创建链表

    Node *head = newNode(1);

    head->next = newNode(2);

    head->next->next = newNode(3);



    // 打印链表

    printList(head);



    // 释放链表

    freeList(head);



    return EXIT_SUCCESS;

}

总结

动态内存分配是C语言中处理复杂数据结构的重要工具。通过合理使用malloccallocreallocfree函数,可以灵活地管理内存资源,避免静态内存分配带来的限制。在使用动态内存分配时,需要注意以下几点:

  • 「检查分配结果」:每次调用malloccallocrealloc后,都要检查返回值是否为NULL,以确保内存分配成功。
  • 「初始化内存」:使用calloc可以方便地初始化内存为0,而malloc分配的内存未初始化,使用前需手动初始化。
  • 「释放内存」:使用完动态分配的内存后,应及时调用free释放,避免内存泄漏。
  • 「避免悬空指针」:释放内存后,将指针置为NULL,避免后续操作导致未定义行为。

通过上述示例和注意事项,可以更好地理解和应用C语言中的动态内存分配技术。

标签:gt,int,NULL,内存,动态内存,printf,array,数据结构,分配
From: https://blog.csdn.net/wang15510689957/article/details/144628813

相关文章

  • [数据结构学习笔记3] 数组
    数组是用于存放一组数据,把这组数据存放在连续的空间里。通常有插入,删除,查找,访问等操作。举例:购物清单,初始状态:清单:牛奶->鸡蛋->奶油->火腿->果汁下标:0      1     2      3     4插入:1.插在末尾清单:牛奶->鸡蛋->奶......
  • 数据结构与算法之查找
    查找的概述1.查找操作的定义查找是按照关键字进行的检索。查找表是由同一类型的数据元素构成的集合,关键字是数据元素(或记录)中某个数据项的值,用它可以标识(或识别)一个数据元素。其中,主关键字可以唯一标识一个数据元素,而次关键字则不能。2.查找表的四种操作查询某个特......
  • 可持久化数据结构
    可持久化平衡树复习了一下fhq。普通可持久化平衡树和主席树类似地,可持久化数据结构的精髓在于对每次进行次数为\(polylog\)级别的操作进行重开点,以此用尽可能小的时空损耗来保存每次操作完的全树状态。国内常用的可持久化平衡树是fhq,容易想到地,就是将它的split和merge操作进......
  • 数据结构与算法学习笔记----快速幂
    数据结构与算法学习笔记----快速幂@@author:明月清了个风@@firstpublishtime:2025.1.2ps⭐️快速幂的两道模版题,快速幂,乘法逆元,费马小定理Acwing875.快速幂[原题链接](875.快速幂-AcWing题库)给定n......
  • 基于MSWA相继加权平均的交通流量分配算法matlab仿真
    1.程序功能描述基于MSWA相继加权平均的交通流量分配算法matlab仿真.如图所示交通网络中,包含6个节点、11各路段、9个OD对。经枚举可得每个OD对间存在3条无折返有效路径,共27条。 2.测试软件版本以及运行结果展示MATLAB2022A版本运行  3.核心程序ifm==1......
  • 数据结构:串
    文章目录串的基本概念串的相关操作串的代码与运行结果串的基本概念1.串长:串的长度(字符个数)称作串长。2.空串:长度为0的字符串。3.主串:包含所有子串的串为主串。4.子串:串中任意连续的字符组成的子序列称为该串的子串。串的相关操作串的操作有生成串,复制串,串连接,......
  • 【初阶数据结构与算法】排序算法总结篇(每个小节后面有源码)(直接插入、希尔、选择、堆
    文章目录一、直接插入排序二、希尔排序三、直接选择排序四、堆排序五、冒泡排序六、快速排序七、归并排序八、计数排序九、非递归快速排序十、非递归归并排序本篇内容将从稳定性与复杂度等角度分析排序算法,列出它们的特点、优点以及缺点,希望大家有所收获,如果想更加细......
  • 【Azure Event Hub】讨论Event Hub服务消费端延迟|分区重分配问题
    问题描述EventHub消费端消费事件延迟,并且有重新分配分区等行为,讨论这种现象的可能原因。 问题解答EventHub如果有大量的Rebalancing请求,就会导致事件消费延迟。而Rebalance的原因也与服务端和消费端的心跳探测有关,如果服务端失去了消费端的心跳请求,触发Rebalance操作......
  • [数据结构学习笔记2] 大O法表示程序的时间复杂度
    程序运行都是需要时间的,我们用大O法来表示,程序在最坏情况下,运行时间和输入规模的关系。一般有这么几种大O时间:快:闪电:O(1)-常量复杂度-和输入无关;比如通过数组下标访问元素;简单数学运算,如看末尾数字是否是基数;火箭:O(logn)-对数复杂度-时间增长随数字规模增长缓慢;这种......
  • [数据结构学习笔记1] 为什么需要有数据结构
    程序本质上就是用来读取数据,然后操作数据,最后生成数据的。如果数据能被有效,或者有结构的展现,那将极大方便程序操作。举例:我们家里有很多工具,剪刀,锤子,斧头,扳手,放大镜,六角扳手,螺丝刀,尺子,卷尺,螺丝,便利贴等等。我们可以怎样收纳这些工具,使得我们后续可以方便的使用呢?第一种,我们家有......