C语言基础语法-教案10(从小白到劝退之内存管理)

C/C++实战入门:从核心语法到项目构建的完整路径 指针与内存管理是C/C++编程的核心基础,理解变量、数组在内存中的布局以及动态内存分配原理,是掌握系统级编程的关键。面向对象编程和标准模板库(STL)等技术,通过封装、继承和多态等机制,提升了代码的复用性和可维护性,而STL中的容器和算法则极大地提高了开发效率。这些技术的价值在于能够构建高性能、资源可控的系统软件和底层组件。在应用场景上,从实现通讯录管理系统、简易HTTP服务器,到模仿STL容器或简易数据库,都是将理论知识转化为工程实践的有效途径。本文基于一位资深开发者的实战经验,系统梳理了C/C++从语法 阅读详情

最近给大家争取到一个 深夜福利

保证你在深夜手机刷到 嘎嘎香~

那就是  大流量卡

缺点:月租太便宜 

185GB~

100分钟通话时长~

长期套餐~

畅想自由的气息

流量自由的同时还拥有超长通话,而且免费领取。

废话不多说直接上图。

名额有限,感兴趣的家人私我或者直接加微信:lyg15314144781

流量卡

C进程内存布局

任何一个程序,正常运行都需要内存资源,用来存放诸如变量、常量、函数代码等等。这些不同的内容,所存储的内存区域是不同的,且不同的区域有不同的特性。因此我们需要研究财经处内存布局,逐个了解不同内存区域的特性。

每个C语言进程都拥有一片结构相同的虚拟内存,所谓的虚拟内存,就是从实际物理内存映射出来的地址规范范围,最重要的特征是所有的虚拟内存布局都是相同的,极大地方便内核管理不同的进程。例如三个完全不相干的进程p1、p2、p3,它们很显然会占据不同区段的物理内存,但经过系统的变换和映射,它们的虚拟内存的布局是完全一样的。

  • PM:Physical Memory,物理内存。
  • VM:Virtual Memory,虚拟内存。

将其中一个C语言含如进程的虚拟内存放大来看,会发现其内部包下区域:

  • 栈(stack)
  • 堆(heap)
  • 数据段
  • 代码段

虚拟内存中,内核区段对于应用程序而言是禁闭的,它们用于存放操作系统的关键性代码,另外由于 Linux 系统的历史性原因,在虚拟内存的最底端 0x0 ~ 0x08048000 之间也有一段禁闭的区段,该区段也是不可访问的。

虚拟内存中各个区段的详细内容

栈内存

  • 什么东西存储在栈内存中?
    • 环境变量
    • 命令行参数
    • 局部变量(包括形参)
  • 栈内存有什么特点?
    • 空间有限,尤其在嵌入式环境下。因此不可以用来存储尺寸太大的变量。
    • 每当一个函数被调用,栈就会向下增长一段,用以存储该函数的局部变量。
    • 每当一个函数退出,栈就会向上缩减一段,将该函数的局部变量所占内存归还给系统。
  • 注意:
    • 栈内存的分配和释放,都是由系统规定的,我们无法干预。

  • 示例代码:
void func(int a, int *p) // 在函数 func 的栈内存中分配
{
    double f1, f2;        // 在函数 func 的栈内存中分配
    ...                   // 退出函数 func 时,系统的栈向上缩减,释放内存
}

int main(void)
{
    int m  = 100;  // 在函数 main 的栈内存中分配
    func(m, &m);  // 调用func时,系统的栈内存向下增长
}

静态数据

C语言中,静态数据有两种:

  • 全局变量:定义在函数外部的变量。
  • 静态局部变量:定义在函数内部,且被static修饰的变量。
  • 示例:
int a = 100; // 全局变量,退出整个程序之前不会释放
void f(void)
{
    static int b = 200; // 静态局部变量,退出整个程序之前不会释放
    printf("%d\n", b);
    b++;
}
int main(void)
{
    f();
    f(); // 重复调用函数 f(),会使静态局部变量 b 的值不断增大
}
  • 为什么需要静态数据?
  1. 全局变量在默认的情况下,对所有文件可见,为某些需要在各个不同文件和函数间访问的数据提供操作上的方便。
  2. 当我们希望一个函数退出后依然能保留局部变量的值,以便于下次调用时还能用时,静态局部变量可帮助实现这样的功能。
  • 注意1:
    • 若定义时未初始化,则系统会将所有的静态数据自动初始化为0
    • 静态数据初始化语句,只会执行一遍。
    • 静态数据从程序开始运行时便已存在,直到程序退出时才释放。
  • 注意2:
    • static修饰局部变量:使之由栈内存临时数据,变成了静态数据。
    • static修饰全局变量:使之由各文件可见的静态数据,变成了本文件可见的静态数据。

数据段与代码段

  • 数据段细分成如下几个区域:
    • .bss 段:存放未初始化的静态数据,它们将被系统自动初始化为0
    • .data段:存放已初始化的静态数据
    • .rodata段:存放常量数据
  • 代码段细分成如下几个区域:
    • .text段:存放用户代码
    • .init段:存放系统初始化代码

int a;       // 未初始化的全局变量,放置在.bss 中
int b = 100; // 已初始化的全局变量,放置在.data 中

int main(void)
{
    static int c;       // 未初始化的静态局部变量,放置在.bss 中
    static int d = 200; // 已初始化的静态局部变量,放置在.data 中
    
    // 以上代码中的常量100、200防止在.rodata 中
}
  • 注意:数据段和代码段内存的分配和释放,都是由系统规定的,我们无法干预。

堆内存

堆内存(heap)又被称为动态内存、自由内存,简称堆。堆是唯一可被开发者自定义的区段,开发者可以根据需要申请内存的大小、决定试用的时间长短等。但又由于这是一块系统“飞地”,所有的细节均由开发者自己把握,系统不对此做任何干预,给予开发者绝对的“自由”,但也正因如此,对开发者的内存管理提出了很高的要求。对堆内存的合理使用,几乎是软件开发中的一个永恒的话题。

  • 堆内存基本特征:
    • 相比栈内存,堆的总大小仅受限于物理内存,在物理内存允许的范围内,系统对堆内存的申请不做限制。
    • 相比栈内存,堆内存从下往上增长。
    • 堆内存是匿名的,只能由指针来访问。
    • 自定义分配的堆内存,除非开发者主动释放,否则永不释放,直到程序退出。

  • 相关API:
    • 申请堆内存:malloc() / calloc()
    • 清零堆内存:bzero()
    • 释放堆内存:free()

功能

申请堆内存

所需头文件

#include

函数原型

void *malloc(size_t size);

void *calloc(size_t count, size_t size);

参数

size

所申请的一块堆内存的大小,单位是字节

count

所申请的堆内存的块数,所有的内存块是连续分布的、无间隔的

返回值

成功

指向子串的指针

失败

NULL

功能

清零指定内存

所需头文件

#include

函数原型

void bzero(void *s, size_t n);

参数

s

指向要清零的内存的指针

n

要清零的内存大小,单位是字节

返回值

无

功能

释放堆内存

所需头文件

#include

函数原型

void free(void *ptr);

参数

ptr

堆内存指针

返回值

无

  • 示例:
int *p = malloc(sizeof(int)); // 申请1块大小为 sizeof(int) 的堆内存
bzero(p, sizeof(int));        // 将刚申请的堆内存清零

*p = 100; // 将整型数据 100 放入堆内存中
free(p);  // 释放堆内存

// 申请3块连续的大小为 sizeof(double) 的堆内存
double *k = calloc(3, sizeof(double));

k[0] = 0.618;
k[1] = 2.718;
k[2] = 3.142;
free(k);  // 释放堆内存
  • 注意:
    • malloc()申请的堆内存,默认情况下是随机值,一般需要用 bzero() 来清零。
    • calloc()申请的堆内存,默认情况下是已经清零了的,不需要再清零。
    • free()只能释放堆内存,不能释放别的区段的内存。
  • 释放内存的含义:
    • 释放内存意味着将内存的使用权归还给系统。
    • 释放内存并不会改变指针的指向。
    • 释放内存并不会对内存做任何修改,更不会将内存清零。

手把手教你用Simulink搭建交流异步电机矢量控制模型(附完整仿真文件) 本文详细介绍了如何使用Simulink搭建交流异步电机矢量控制模型,涵盖系统架构设计、关键模块实现、PI调节器参数整定及仿真分析等核心内容。通过实战指南和完整仿真文件,帮助读者掌握矢量控制技术,提升电机控制系统的设计与调试能力。 阅读详情

相关推荐

无人机通信电台--XBee-PRO 900HP (S3B)

XBee PRO S3B也称为XBee-900HP无线模块,它是一款工作在频段900~928MHz之间,基于FHSS跳频技术的远距离无线数传电台核心模块。常用型号如下: 类别 型号 开发套件 XKB9-DMT-UHP XBee-PRO 900HP (S3B) DigiMesh模块,200Kbps,软天线 XBP9B-DMWT-002 XBee-PRO 900HP (S3B)...

low米的博客 4505

C语言基础语法-教案15(从小白到劝退之存储期)

C语言基础语法-教案15(从小白到劝退之存储期)

LINUX823的博客 869

【开源~磁悬浮】零代码,纯硬件闭环:从霍尔到H桥的磁悬浮稳定术

本文详细介绍了如何不依赖任何代码,仅通过模拟和数字电路的组合,实现一个完整的磁悬浮闭环控制系统。从霍尔传感器检测位置,到运放电路进行信号调理与模拟PID控制,再到H桥驱动电磁铁执行纠偏,全程使用基础电子元器件搭建。文章深入剖析了系统原理、电路设计、调试技巧与实践经验,展现了纯硬件实现自动控制的独特魅力与挑战。

perl8的博客 622

C语言基础语法-教案11(从小白到劝退之函数)

C语言基础语法-教案11(从小白到劝退之函数)

LINUX823的博客 563

LSTM 怎么进行二维数据的输入呢

尽管LSTM并不天然地适用于处理图像、视频等二维数据,但通过时间序列化、卷积特征提取和双向LSTM等方法,我们可以将二维数据转化为适合LSTM输入的形式,从而利用LSTM的强大记忆能力和长期依赖学习能力对二维数据进行建模。未来的研究方向可以考虑将LSTM与其他模型结合,例如将LSTM与卷积神经网络(Convolutional Neural Network, CNN)结合,利用CNN提取图像的空间特征,然后利用LSTM学习时间序列的长期依赖;

xiamu_CDA的博客 1037

R语言 百度坐标转换至WGS84坐标

本文利用R语言封装了百度坐标转换至WGS84坐标的函数,亲测有效,提供了便捷的百度坐标转换方法。

qingchen98的博客 2135

吃透这7本正版C语言教程,从小白到编程大神,别再走弯路!

一、学C语言的人,90%都选错了教程!你是不是也抱着一腔热血想学C语言,却对着满屏晦涩的教程无从下手?是不是刷遍全网找资料,最后要么看不懂,要么学了用不上,白白浪费时间?

ney77的博客 260

AD22里面封装修改后,同步到PCB图里面

【摘要】本文介绍了Altium Designer 22中同步更新元件封装的三种方法:1)从PCB库直接更新:在PCB库面板右键选择"Update PCB With[封装名]";2)通过原理图标准更新:使用Design->Update PCB Document菜单;3)在PCB编辑器中验证更新:通过Tools->Update From PCB Libraries菜单。所有方法最终都需通过ECO(工程变更订单)确认变更,建议执行前仔细核对变更内容。这些方法适用于AD22及早期版本

whm128的博客 1762

C语言从入门到实战:环境搭建、核心语法与内存管理全解析

C语言作为系统编程和底层开发的基石,其核心价值在于对计算机内存和硬件的直接控制能力。理解其工作原理,关键在于掌握内存管理、指针操作和编译链接过程。这些基础概念不仅是编写高效、稳定代码的前提,也是深入学习操作系统、嵌入式系统等领域的必备技能。在工程实践中,从环境搭建(如VSCode+GCC配置)、数据类型与指针的精确使用,到动态内存分配(malloc/free)和文件操作,每一步都要求开发者对底层细节有清晰认识。本文通过一个完整的学生管理系统实战项目,串联起结构体、动态数组、文件IO等关键知识点,并深入探讨了

weixin_32308101的博客 306

机器学习项目实战案例数据集

本专栏整理了《机器学习项目实战案例》,内包含了各种不同的机器学习项目,包含项目原理以及源码,每一个项目实例都附带有完整的代码+数据集。

优快云 精品推荐 3636

YOLOv8改进策略【损失函数篇】| 2024 引进Focaler-IoU损失函数 加强边界框回归 (Focaler-DIoU、Focaler-GIoU、Focaler-CIoU)

本文记录的是改进YOLOv8的损失函数,将其替换成。现有研究通过利用边界框之间的几何关系来提高回归性能,但忽略了困难样本和简单样本分布对边界框回归的影响。不同检测任务中困难样本和简单样本的分布不同,对于简单样本占主导的检测任务,关注简单样本的边界框回归有助于提高检测性能;对于困难样本比例较高的检测任务,需要关注困难样本的边界框回归。,提高检测器在不同检测任务中的性能。实现的。

Limiiiing的博客 1222

学个 P 的Java,从劝退的角度来跟你讲讲Java需要学什么

这篇文章我想从劝退的角度,来拢一波身为一个Javaer不管是从工作还是面试都需要掌握的一些要点。 从初学者到老油条的节奏来写,来看看会不会被劝退吧!随便推荐一些相关的资料。 学 Java 都要学些啥呢? Java 基础学了没? 什么基本数据类型、操作符、控制语句等基本语法就不说了。 一些特性搞明白了嘛? 面向对象和面向过程 反射与代理 接口与继承 泛型 异常处理 注解 … 常用类库用的溜嘛? 文件I/O操作 时间日期操作 字符串操作 集合类熟不熟? List、ArrayList、Linked

weixin_57018493的博客 832

(汇总篇)语义SLAM相关开源方案| 全球优秀作者与实验室 | SLAM学习资料整理

SLAM 与深度学习相结合的工作当前主要体现在两个方面,一方面是将语义信息参与到建图、位姿估计等环节中,另一方面是端到端地完成 SLAM。针对建图的工作一方面是利用几何信息进行稠密重建,另一方面很多工作利用语义信息达到了很好的语义重建效果,三维重建、SFM。动态 SLAM 也是一个很值得研究的话题,这里不太好分类,很多工作用到了语义信息或者用来三维重建,收集的方案相对较少。优化可能是 SLAM 中最难的一部分了吧 +_+ ,一般都是直接用现成的因子图、图优化方案,要创新可不容易。

熊猫小妖的AI世界 7867

为啥学C语言绕不开指针?懂它封神,不懂直接劝退,真相太扎心

一、学C的人,一半栽在指针上,一半靠它拿高薪无数程序员入门C语言时,都有过同一个崩溃瞬间:对着指针的*和&抓耳挠腮,明明看书上写的是“存储内存地址的变量”

ney77的博客 375

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

使用LiuJuan20260223Zimage进行C语言基础教学:交互式代码讲解与练习生成

本文介绍了如何在星图GPU平台上自动化部署LiuJuan20260223Zimage镜像,以进行高效的C语言基础教学。该镜像能作为AI编程导师,提供交互式代码讲解、图解生成及动态练习批改,尤其擅长将指针、内存管理等抽象概念转化为易于理解的示例和实战练习,助力初学者快速入门。

weixin_35390379的博客 35

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

上一篇: C语言基础语法-教案09(搞定指针就搞定C语言 指针进阶)
下一篇: C语言基础语法-教案11(从小白到劝退之函数)
栈时没有名字
博客等级 码龄5年 289粉丝 47原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值