内存(动态开辟)———C语言

news2024/9/25 13:25:35

内存管理:

 1.C语言运行时的内存分配

2.static关键字

1.修饰变量

局部变量:

        <1>在编译的过程中,会在数据区为该变量开辟空间,如果代码中未对其进行初始化,则系统默认初始化为0。

        <2>用static修饰的局部变量,会延长局部变量的生命周期

#include <stdio.h>
void fun(){
        static int var= 10;
        var++;
        printf("var=%d\n",var);}
int main(){
        fun();
        fun();
        fun();
        return 0;
}

修饰全局变量

        <1>static修饰全局变量,会在数据区域分配存储空间,如果全局变量未初始化,编译器会自动初始化为0.

        <2>static修饰全局变量,会限制全局变量的使用范围,让其只能在本文件使用,其他文件不能使用。


#include <stdio.h>
static int global_var = 10;

main.c

#include <stdio.h>
extern int global_var;
void fun(){
    printf("global_var = %d\n", global_var);
    return;
}//此时就不能被正常使用

2.修饰函数:

修饰函数后函数变为静态函数

<1>静态函数只能在声明它的文件中使用,其他文件不能引用该函数

<2>不同的文件可以使用相同名字的静态函数,互不影响

动态内存分配:

固定开辟的内存大小在程序运行时我们无法准确掌握,因此就需要进行动态开辟内存

<1>malloc和free:

如果开辟成功,则返回一个指向开辟空间的指针如果开辟失败,则返回一个NULL指针,因此malloc的返回值要进行检查返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用时由使用者决定如果参数size=0,malloc的行为是标准未定义的,取决于编译器

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
int main() {
    int* p =(int*) malloc(sizeof (int)*10);
    //动态开辟内存
    if(NULL==10){
        printf("%s\n", strerror(errno));//用于判断内存开辟是否失败
    } else{
        for (int i = 0; i < 10; i++) {
            *(p + i) = i + 1;//进行赋值
        }                //打印
        for (int i = 0; i < 10; i++) {
            printf("%-4d", *(p + i));
        }
        printf("\n");
    }
    return 0;
}

void free(void* memblock)

  • 如果参数memblock指向的空间不是动态开辟的,那么free函数的行为是未定义的
  • 如果参数memblock是NULL指针,则函数什么也不做

Tips:

<1>C语言中可以创建变长数组,C99标准支持

<2> malloc和free都声明在stdlib.h的头文件中

<2>calloc:

void* calloc(size_t num,size_t size);

与malloc不同的是calloc会返回地址之前把申请的每个字节初始化为0

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main() {
        // 向内存申请15个整型类型的空间
        int* p = (int*)calloc(10, sizeof(int));
        //判断是否开辟成功
        if (NULL == p) {
                // 打印错误信息
                printf("%s\n", strerror(errno));
        }
        else {
                // 给10个空间进行赋值并打印
                for (int i = 0; i < 10; i++) {
                        *(p + i) = i + 1;
                }
                // 打印
                for (int i = 0; i < 15; i++) {
                        printf("%-4d", *(p + i));
                }
        printf("\n");
                // 释放空间
                free(p);
                p = NULL;
        }
        return 0;
}

<3>realloc:

realloc函数会让动态内存管理更灵活,调整对应的内存地址大小

原型:void* realloc(void* ptr,size_t size)

  1. ptr是要调整的内存地址
  2. size 调整之后的内存大小
  3. 返回值为调整之后的内存起始地址
  4. 这个函数会将原内存中的数据迁移到新的内存空间
  5. 这个函数会将原内存空间自动释放
  6. realloc在调整动态分配的内存空间大小时,有两种情况  

    <1>如果原指针指向的空间之后有足够的内存空间可以追加,则直接追加

    <2>如果原指针指向的空间之后没有足够的内存空间,该函数会重新找一块新的内存区域,按照指定大小重新开辟空间。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main() {
        // 向内存申请5个整型类型的空间
        int* p = (int*)calloc(5, sizeof(int));
        //判断是否开辟成功
        if (NULL == p)
        {
                // 打印错误信息
                printf("%s\n", strerror(errno));
        }        else        {
                //给5个空间进行赋值并打印
            for (int i = 0; i < 5; i++) {
                        *(p + i) = i + 1;
                }
                // 在这里20个字节的空间不能满足要求,需要进行调整
                int* np = (int*)realloc(p, 40);
                for (int i = 5; i < 10; i++) {
                        *(np + i) = i + 10;
                }
                //打印
                for (int i = 0; i < 10; i++) {
          printf("%-4d", *(np + i));
                }
                printf("\n");
        // 释放空间
        free(np);
        np=NULL;
        }
        return 0;
}

常见的动态内存错误:

1. 对NULL指针的解引用操作

int main(){
    int* p = (int*)malloc(-1);
    *p = 20;
    // 如果分配失败,P=NULL,此时就会报错
    free(p);
    p = NULL;
    return 0;
}

2. 对动态开辟空间的越界访问

int main() {
    int i = 0;
    int* p = (int*)malloc(10 * sizeof(int));
    if (NULL == p)     {
        exit(EXIT_FAILURE);
    }    else     {
        for (int i = 0; i <= 10; i++) {
            *(p + i) = i + 1;
     // 越界访问        }
    }
    free(p);
    p = NULL;
    return 0;
}

3. 使用free释放一块动态开辟内存的一部分

int main() {
    int* p = (int*)malloc(10 * sizeof(int));
    if (NULL == p)
    {
        exit(EXIT_FAILURE);
    }    else     {
        p++;
        free(p);
    // p不再指向动态内存的起始地址
        p = NULL;
    }
    return 1;
}  

4. 对非动态开辟的空间使用free函数

int main() {
    int  a = 10;
    int* p = &a;
    free(p);
    // p不是动态开辟的空间
    p = NULL;
    return 0;
}

5. 对同一块动态内存多次释放

 int main() {
    int* p = (int*)malloc(20);
    if (NULL == p) {
        exit(EXIT_FAILURE);
    }
    free(p);
    free(p);
    //重复释放
    p = NULL;
    return 0;
}
    // 如何避免重复释放
int main() {
    int* p = (int*)malloc(20);
    if (NULL == p) {
        exit(EXIT_FAILURE);
    }
    free(p);
    p = NULL;
    // 释放完成后,将指针置为NULL
    free(p); // free(NULL)时,此函数啥功能都不做
    return 0;
}

6. 动态开辟的内存忘记释放(内存泄露)

int main() {
    while (1) {
        malloc(10);
    }
    return 1;
}

     

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2053198.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

a股市场的股票怎么做期权交易

在金融市场中&#xff0c;A股股票期权是一种重要的衍生金融工具&#xff0c;它赋予持有者在未来某一特定日期以预定价格买入或卖出股票的权利。了解期权交易流程对于投资者至关重要&#xff0c;本文将详细介绍a股市场的股票怎么做期权交易&#xff1f;本文来自&#xff1a;期权…

【软件测试】测试阶段、评审、瀑布式流程

软件测试 测试阶段评审瀑布式流程 测试阶段 冒烟测试&#xff08;Smoke Testing&#xff09;&#xff1a; 冒烟测试是一种快速的初步测试&#xff0c;通常在开发周期的早期进行&#xff0c;用以验证软件的基本功能是否按预期工作。它通常在软件构建完成后立即执行&#xff0c;以…

【windows系统】应用与功能下卸载程序提示Windows找不到文件解决办法

我们使用windows系统的时候&#xff0c;想要删除某个程序&#xff0c;可以通过windows系统设置中的添加或删除程序来操作&#xff0c;如下图所示 打开如图下所示应用和功能界面&#xff0c;可以对程序进行卸载 如图下所示&#xff0c;我们可以通过这种方式卸载掉电脑中的程序 但…

ClickHouse集群的安装

目录 1.clickhouse中文文档地址 2.centos安装部署 2.1采用tgz的方式安装 2.2修改配置文件 2.3修改数据目录 2.4创建角色和目录 3 集群安装 3.1配置文件修改 3.2启动zookeeper 3.3启动clickhouse-server 3.4任意节点连接clickhouse 3.5查看集群 3.6建库 3.7查看数…

【Linux 驱动】IMX6ULL pinctrl驱动

1. 概述 Linux 驱动讲究驱动分离与分层&#xff0c;pinctrl 和 gpio 子系统就是驱动分离与分层思想下的产物。pinctrl顾名思义就是引脚控制&#xff0c;用来配置比如引脚mux复用信息&#xff0c;引脚电器属性&#xff08;比如上/下拉、速度、驱动能力等&#xff09;信息。gpio顾…

学会区分大模型——大模型的分类,让你更清晰的认识大模型

乱花渐欲迷人眼&#xff0c;学会从根本上认识问题 现在市面上大模型如百花齐放&#xff0c;对很多人来说一堆大模型带来的不是简单方便&#xff0c;而是乱七八糟以及迷茫。 因为不知道不同的大模型之间有什么区别&#xff0c;也不知道自己需要什么样的大模型&#xff1b;就拿…

【C++题解】1375. 拦截导弹方案求解

问题&#xff1a;1375. 拦截导弹方案求解 类型&#xff1a;贪心 题目描述&#xff1a; 某国为了防御敌国的导弹袭击&#xff0c;发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷&#xff1a; 虽然它的第一发炮弹能够到达任意的高度&#xff0c;但是以后每一发炮弹都…

理解Flink数据流图

前言 在大数据处理的世界里&#xff0c;Apache Flink 已经成为处理实时数据流的一个强大工具。Flink 提供了一种高度灵活的方法来构建复杂的数据处理管道&#xff0c;其核心是所谓的 DataFlow 图模型。本文将带你深入了解 Flink DataFlow 图的基础知识&#xff0c;帮助你理解它…

Hadoop入门基础(一):深入探索Hadoop内部处理流程与核心三剑客

在大数据的世界里&#xff0c;处理海量数据的需求越来越多&#xff0c;而Hadoop作为开源的分布式计算框架&#xff0c;成为了这一领域的核心技术之一。 一、Hadoop简介 Hadoop是Apache Software Foundation开发的一个开源分布式计算框架&#xff0c;旨在使用简单的编程模型来…

别再问了!微信小程序的那些事儿,一文搞定

微信小程序是一种无需下载安装即可使用的应用&#xff0c;它嵌入在微信生态中&#xff0c;用户通过微信扫一扫或搜索即可快速访问。 无论是购物、订餐、预约服务&#xff0c;还是玩个小游戏、看篇文章&#xff0c;都不需要下载额外的APP&#xff0c;直接就能在微信里搞定。不会…

Leading SAFe领导大规模敏捷认证公开课

课程简介 SAFe – Scaled Agile Framework是目前全球最广泛使用的大规模敏捷框架&#xff0c;也是全球敏捷相关认证中增长最快、最受认可的规模化敏捷认证。全球已有超过120万名SAFe认证专业人士。据官方统计&#xff0c;获得SAFe认证的IT专业人士平均工资增长13,000美元&…

C++:模拟实现string

前言&#xff1a; 为了更好的理解string底层的原理&#xff0c;我们将模拟实现string类中常用的函数接口。为了与std里的string进行区分&#xff0c;所以用命名空间来封装一个自己的strin类。 string.h #pragma once #define _CRT_SECURE_NO_WARNINGS 1#include<iostream&…

arm 的寄存器概述(8)

关于寄存器的概述。 带 三角形的是 这种模式下 独有的寄存器&#xff0c;也就是说&#xff0c;FIQ模式下与 SYstem/user 模式下&#xff0c;虽然都有r8 寄存器&#xff0c;但是不是一个东西。 r13 (SP ) 这是堆栈指针&#xff0c; r15(PC ) 这是 code 的指针。 r14(LR ), 这…

自动化与高效设计:推理技术在FPGA中的应用

想象一下&#xff0c;你正在设计一个复杂的电路系统&#xff0c;就像在搭建一座精巧的积木城堡。你手头有各种形状和功能的积木块&#xff0c;这些积木块可以组合成任何你需要的结构。在这个过程中&#xff0c;你有两种主要的方法&#xff1a;一种是手动挑选和搭建每一块积木&a…

安装JDK与配置环境变量

安装JDK与配置环境变量 JDK安装包所在路径&#xff1a;/opt/software/jdk-8u221-linux-x64.tar.gz 详细步骤 安装JDK与配置环境变量一、进入JDK安装目录/opt/software二、解压“jdk-8u221-linux-x64.tar.gz”安装包至当前目录三、查看/opt/software/目录下解压文件四、编辑系统…

鹅厂探索国漫新方向,谁家新作能不负期待?

上周一年一度的腾讯视频动漫大赏年度发布会结束了&#xff0c;但动漫迷们的讨论却没有停止。此次的片单分为“气”“大怪”“阁”三大主题&#xff0c;今天来和大家回顾解读一下“气”和“阁”有哪些看点吧。 首先想谈一谈“阁”&#xff0c;它是平台在内容升级思路上的体现&am…

C指针汇总——藏在数组名与指针之间的异同及使用细节

指针与数组的异同 数组名&#xff1a; 是一个指针常量(数组名的值是数组首元素的指针常量)&#xff0c;指向数组的首元素。大小固定为整个数组的大小。无法被改变或重新赋值(这里指数组名不能被赋值(指针常量不能指向其它地址)&#xff0c;数组元素是可以被重新设置的)。无法进…

企业CAD图纸加密软件推荐!2024年好用的10款CAD图纸加密软件排行

在现代企业中&#xff0c;CAD图纸作为重要的设计和工程数据&#xff0c;其安全性和保密性至关重要。为了防止图纸被非法获取、篡改或滥用&#xff0c;选择一款高效的CAD图纸加密软件显得尤为重要。本文将为您推荐2024年市场上十款好用的CAD图纸加密软件&#xff0c;帮助企业保护…

2024最新50道NLP和人工智能领域面试题+答案(中文+英文双版本)

编者按&#xff1a;分享一个很硬核的免费人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 可以当故事来看&#xff0c;轻松学习。 中文版本 自然语言处理 (NLP)已成为语言学、人工智能和计算机科学交叉领域的变革性领域。随着文本数据量的不断增加&…

图形编辑器基于Paper.js教程15:在Paper.js中实现拖拽图片导入画布功能

在现代Web开发中&#xff0c;用户体验是至关重要的。而拖拽文件上传的功能&#xff0c;不仅直观易用&#xff0c;还提升了用户与界面的交互体验。在这篇文章中&#xff0c;我们将探讨如何使用Paper.js和HTML5的拖放API&#xff0c;来实现将图片文件直接拖拽并导入到Paper.js的画…