当前位置: 首页 > news >正文

C语言精讲-12

C语言精讲-12

C语言的内存管理

内存管理函数包含在头文件include<stdlib.h>;用于动态分配内存;
在这里插入图片描述

1.malloc函数

函数原型:void* malloc(size_t size);
返回值:若内存分配成功,malloc 会返回一个指向所分配内存起始位置的指针;若分配失败,则返回 NULL。
参数:size表示你要分配的内存字节数。

2.free函数

函数原型:void free(void *ptr);
参数:ptr指向之前由 malloc、calloc 或 realloc 分配的内存块的指针。
返回值·:NULL;

案例

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    //动态分配一块能存放 10 个 int 类型数据的内存
    int *ptr = (int*)malloc(10 * sizeof(int));
    if (ptr == NULL) {
        printf("内存分配失败!\n");
        return 1;
    }
    // 给分配的内存赋值
    int i=0;
    for (i = 0; i < 10; i++) {
        ptr[i] = i;
    }
    // 输出分配内存中的值
    for (i = 0; i < 10; i++) {
        printf("%d ", ptr[i]);
    }
    printf("\n");
    // 释放分配的内存
    free(ptr);
    return 0;
}

在这里插入图片描述

3.calloc函数

函数原型:void* calloc(size_t num, size_t size);
参数:num:需要分配的元素个数。size:每个元素的大小(以字节为单位)。
返回值:如果内存分配成功,calloc 会返回一个指向所分配内存起始位置的指针;若分配失败,则返回 NULL。

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

int main() {
    // 动态分配 10 个 int 类型元素的内存
    int *ptr = (int*)calloc(10, sizeof(int));
    if (ptr == NULL) {
        printf("内存分配失败!\n");
        return 1;
    }
    // 输出分配内存中的值,初始值应为 0
    int i=0;
    for (i = 0; i < 10; i++) {
        printf("%d ", ptr[i]);
    }
    printf("\n");
    // 释放分配的内存
    free(ptr);
    return 0;
}

在这里插入图片描述

4.realloc函数

函数原型:void* realloc(void *ptr, size_t size);
参数:ptr:指向之前由 malloc、calloc 或 realloc 分配的内存块的指针。若 ptr 为 NULL,则 realloc 的行为等同于 malloc。size:调整后内存块的新大小(以字节为单位)。
返回值:若内存重新分配成功,realloc 会返回一个指向新分配内存块起始位置的指针;若分配失败,则返回 NULL,并且原内存块不会被释放。

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

int main() {
    // 初始分配 5 个 int 类型元素的内存
    int *ptr = (int*)malloc(5 * sizeof(int));
    int i=0;
    if (ptr == NULL) {
        printf("内存分配失败!\n");
        return 1;
    }
    // 给初始分配的内存赋值
    for (i = 0; i < 5; i++) {
        ptr[i] = i;
    }
    // 输出初始分配内存中的值
    for (i = 0; i < 5; i++) {
        printf("%d ", ptr[i]);
    }
    printf("\n");

    // 重新分配内存,将大小调整为 10 个 int 类型元素
    int *new_ptr = (int*)realloc(ptr, 10 * sizeof(int));
    if (new_ptr == NULL) {
        printf("内存重新分配失败!\n");
        free(ptr);
        return 1;
    }
    ptr = new_ptr;

    // 给新增的内存赋值
    for (i = 5; i < 10; i++) {
        ptr[i] = i;
    }
    // 输出重新分配内存后的所有值
    for (i = 0; i < 10; i++) {
        printf("%d ", ptr[i]);
    }
    printf("\n");

    // 释放重新分配的内存
    free(ptr);
    return 0;
}

在这里插入图片描述

5.要点讲解

5.1void*

void 类型指针(void*)是一种特殊的指针类型,也被称作通用指针。
特性
通用性:void* 类型的指针可以指向任意类型的数据,这意味着它能够存储任何类型变量的地址。
无类型信息:void* 指针本身不包含所指向数据的类型信息。这表明在使用 void* 指针时,你无法直接对其进行解引用操作,必须先将其转换为具体的指针类型。
使用注意事项
解引用前需类型转换:由于 void* 指针不包含类型信息,不能直接进行解引用操作。在使用之前,必须将其转换为具体的指针类型。
指针运算受限:void* 指针不能进行指针运算,因为指针运算需要知道所指向数据的类型大小。如果要进行指针运算,需要先将其转换为具体的指针类型。
内存管理:在使用 void* 指针进行动态内存分配时,要确保在使用完内存后调用 free 函数释放内存,避免内存泄漏。

5.2动态分配内存的基本原则

1)避免分配大量的小内存块。分配堆上的内存有一些系统开销,所以分配许多小的内存块比分配几个大内存块的系统开销大
2)仅在需要时分配内存。只要使用完堆上的内存块,就需要及时释放它,否则可能出现内存泄漏
这里需要遵守原则:谁分配,谁释放。
3)总是确保释放以分配的内存。在编写分配内存的代码时,就要确定在代码的什么地方释放内存。

相关文章:

  • 【Linux】基础开发工具
  • 八大可商用桌面客户端应用开发框架深度指南-优雅草卓伊凡
  • 操作系统基础:05 系统调用实现
  • playwright 教程高级篇:掌握网页自动化与验证码处理等关键技术详解
  • [数据结构]排序 --2
  • 【C++】C++的引用
  • 在 Ubuntu 下通过 Docker 部署 Caddy 服务器
  • C++双链表介绍及实现
  • 从输入URL到页面渲染:浏览器请求的完整旅程解析
  • LLM学习笔记3——使用Docker(vLLM+OpenWebUI)实现本地部署DeepSeek-R1-32B模型
  • 基于HASM模型的高精度建模matlab仿真
  • Go 跨域中间件实现指南:优雅解决 CORS 问题
  • 十五、C++速通秘籍—异常处理
  • 基于Python的经济循环模型构建与可视化案例
  • Matlab添加标题title与标签lable
  • 上层 Makefile 控制下层 Makefile 的方法
  • 解释型语言和编译型语言的区别
  • 安全岗の夺命连环问:(第壹篇)从XSS到0day的灵魂拷问
  • 舵机、震动传感器、超声波使用代码
  • Qt 5.14.2 入门(四)菜单栏和工具栏的创建
  • 2025年4月份CPI环比由降转涨,核心CPI涨幅稳定
  • 报告:4月份新增发行的1763亿元专项债中,投向房地产相关领域约717亿元
  • 数理+AI+工程,上海交大将开首届“笛卡尔班”招生约20名
  • 国家发改委:美芯片药品等领域关税影响全球科技发展,损害人类共同利益
  • 读图|展现城市品格,上海城市影像走进南美
  • 青岛双星名人集团管理权之争:公司迁址,管理层更迭