0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C语言中定义4个内存区间

C语言编程学习基地 来源:C语言编程学习基地 作者:Mr_Li_ 2022-10-19 15:43 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一个正在运行着的C编译程序占用的内存分为代码区、静态数据区、未初始化数据区、堆区 和 栈区5个部分。

C语言中定义4个内存区间是: 代码区, 静态存储区, 栈区, 堆区. 其中栈区和堆区是属于动态存储区可执行文件在存储(也就是还没有载入到内存中)的时候,分为:代码区、静态区和未初始化数据区3个部分。

74a3676c-4f80-11ed-a3b6-dac502259ad0.png

代码区

只读区域,程序运行过程中无法做任何修改的存储区域。用于存放代码和常量。

存放CPU执行的机器指令。通常,代码区是可共享的(即另外的执行程序可以调用它),因为对于频繁被执行的程序,只需要在内存中有一份代码即可。代码区通常是只读的,使其只读的原因是防止程序意外地修改了它的指令。另外,代码区还规划了局部变量的相关信息。

代码区 指令根据程序设计流程依次执行,对于顺序指令,则只会执行一次(每个进程),如果反复,则需要使用跳转指令,如果进行递归,则需要借助栈来实现。

代码段: 代码段通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。

在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等

。代码区的指令中包括操作码和要操作的对象(或对象地址引用)。如果是立即数(即具体的数值,如5),将直接包含在代码中;如果是局部数据,将在栈区分配空间,然后引用该数据地址;如果是BSS区和数据区,在代码中同样将引用该数据地址。另外,代码段还规划了局部数据所申请的内存空间信息。

数据区:可读可写区域,程序运行过程中可做任意修改的存储区域。用于存放变量

静态数据区

该区包含了在程序中明确被初始化的全局变量、静态变量(包括全局静态变量和局部静态变量)和常量数据(如字符串常量),注意 (只初始化一次)。例如,一个不在任何函数内的声明(全局数据):

int max = 99;

使得变量max根据其初始值被存储到初始化数据区中。

static min = 100;

这声明了一个静态数据,如果是在任何函数体外声明,则表示其为一个全局静态变量,如果在函数体内(局部),则表示其为一个局部静态变量。另外,如果在函数名前加上static,则表示此函数只能在当前文件中被调用。

数据段:通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。数据段中的静态数据区存放的是程序中已初始化的全局变量、静态变量和常量。

未初始化数据区

未初始化数据区。亦称BSS区,存入的是全局未初始化变量。BSS这个叫法是根据一个早期的汇编运算符而来,这个汇编运算符标志着一个块的开始。BSS区的数据在程序开始执行之前被内核初始化为0或者空指针(NULL)。例如一个不在任何函数内的声明:

long sum[1000];

将变量sum存储到未初始化数据区。

BSS 段:通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS 是英文Block Started by Symbol 的简称。BSS 段属于静态内存分配,即程序一开始就将其清零了。一般在初始化时BSS段部分将会清零。

栈区

栈区(stack)。由编译器自动分配释放内存的区间,所得的内存空间一般都是连续的,是用来存放函数的参数值、局部变量的值等。存放函数的参数值、局部变量的值,以及在进行任务切换时存放当前任务的上下文内容。其操作方式类似于数据结构中的栈。每当一个函数被调用,该函数返回地址和一些关于调用的信息,比如某些寄存器的内容,被存储到栈区。然后这个被调用的函数再为它的自动变量和临时变量在栈区上分配空间,这就是C实现函数递归调用的方法。

每执行一次递归函数调用,一个新的栈框架就会被使用,这样这个新实例栈里的变量就不会和该函数的另一个实例栈里面的变量混淆。

栈(stack):栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧"{ }"中定义的变量,如int[ ] arr = {1, 2, 3};变量arr ( 数组名) 存储在栈中,变量arr的值(数组元素)存储在堆中(普通结构)(但不包括static 声明的变量,static 意味着在数据段中存放变量)。

除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/ 恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

堆区

堆区(heap)。用于动态内存分配。堆在内存中位于bss区和栈区之间。一般由程序员分配和释放,若程序员不释放,程序结束时有可能由OS回收。堆中的内存区域不是连续的,还是将有效的内存区域经过链表指针连接起来的。

堆(heap): 用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc 等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free 等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。

在将应用程序加载到内存空间执行时,操作系统负责代码段、数据段和BSS段的加载,并将在内存中为这些段分配空间。栈段亦由操作系统分配和管理,而不需要程序员显示地管理;堆段由程序员自己管理,即显式地申请和释放空间。

另外,可执行程序在运行时具有相应的程序属性。在有操作系统支持时,这些属性页由操作系统管理和维护。

C语言程序编译完成之后,已初始化的全局变量保存在数据段中,未初始化的全局变量保存在BSS段中。数据段和代码段都在可执行文件中,由系统从可执行文件中加载;而BSS段不在可执行文件中,由系统初始化。BSS段只保存没有值的变量,所以事实上它并不需要保存这些变量的映像。运行时所需要的BSS段大小记录在目标文件中,但是BSS段并不占据目标文件的任何空间。

堆区与栈区的差异:

在栈上所申请的内存空间是系统自动分配的,所以当我们出了变量所在的作用域后,系统会自动我们回收这些空间,而在堆上申请的空间是要我们自己手动操作的,当出了相应的作用域以后,我们需要调用free或者delete来释放所申请的内存空间,如果我们不及时得对这些空间进行释放,那么内存中的内存碎片就越来越多,从而我们的实际内存空间也就会变的越 来越少,即,孤立的内存块越来越多。

审核编辑 :李倩

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    183

    文章

    7642

    浏览量

    144617
  • 代码
    +关注

    关注

    30

    文章

    4941

    浏览量

    73151
  • C编译
    +关注

    关注

    0

    文章

    4

    浏览量

    3508

原文标题:【零基础学C语言】知识总结十一:C语言的内存四区

文章出处:【微信号:cyuyanxuexi,微信公众号:C语言编程学习基地】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    C语言的编程技巧

    成员是一未知大小的数组,适用于动态分配内存并关联一可变长度的数组。‌ ‌3、匿名结构体和联合体‌:C
    发表于 11-27 06:46

    C语言的分支结构介绍

    1.简单if语句 C语言中的分支结构语句中的if条件语句。 简单if语句的基本结构如下: 代码语言:javascript if(表达式) { 执行代码块; } 其语义是:如果表达式的值为真,则执行其后的语句,否则不执
    发表于 11-25 07:48

    C语言的常量介绍

    、-13; 实型常量:13.33、-24.4; 字符常量:‘a’、‘M’ 字符串常量:”I love china!” 在C语言中,可以用一标识符来表示一常量,称之为符号常量。符号常
    发表于 11-24 07:12

    C语言宏拼接运算符典型使用

    C语言中,##运算符(称为[size=16.002px]标记拼接运算符)用于宏定义中将两标记(token)拼接成一新的标记。它在预处理
    发表于 11-20 08:27

    4C语言基础以及流水灯的实现(4.3 4.4)

    4.3 C语言基本运算符 小学数学学过加、减、乘、除等运算符号以及四则混合运算,而这些运算符号在C语言中也有,但是有些表达方法不一样,并且还有额外的运算符号。在
    的头像 发表于 10-29 15:30 181次阅读

    灵活高效双引擎驱动:ZBUFF让C语言内存操作更智能!

    高性能系统。 一、ZBUFF核心库常用函数 如果小伙伴们此前没有接触过C语言或者不精通C语言,把ZBUFF核心库当成新库来学习即可,建议先从熟悉相关函数的功能及其参数意义入手。 感兴趣
    的头像 发表于 08-11 13:27 439次阅读
    灵活高效双引擎驱动:ZBUFF让<b class='flag-5'>C</b><b class='flag-5'>语言</b><b class='flag-5'>内存</b>操作更智能!

    Windows环境下32位汇编语言中文资料

    电子发烧友网站提供《Windows环境下32位汇编语言中文资料.rar》资料免费下载
    发表于 06-30 15:14 0次下载

    《ESP32S3 Arduino开发指南》第三章 C/C++语言基础

    boolean类型。它的值只有两:false(假)和true(真)。Boolean类型会占用1字节的内存空间。3.2 运算符 C/C++语言中
    发表于 06-10 09:20

    主流的 MCU 开发语言为什么是 C 而不是 C++?

    在单片机的地界儿里,C语言稳坐中军帐,C++想分杯羹?难喽。咱电子工程师天天跟那针尖大的内存空间较劲,C++那些花里胡哨的玩意儿,在这儿真玩
    的头像 发表于 05-21 10:33 779次阅读
    主流的 MCU 开发<b class='flag-5'>语言</b>为什么是 <b class='flag-5'>C</b> 而不是 <b class='flag-5'>C</b>++?

    深入理解C语言C语言循环控制

    改变程序的执行流程,使代码更加灵活和可控。本文将详细介绍这些语句的作用及其应用场景,并通过示例代码进行说明。Part.1break语句C语言中break语句有两种
    的头像 发表于 04-29 18:49 1735次阅读
    深入理解<b class='flag-5'>C</b><b class='flag-5'>语言</b>:<b class='flag-5'>C</b><b class='flag-5'>语言</b>循环控制

    C语言中结构体与联合体的深度解析:内存布局与应用场景

    一、基础概念与核心差异 1.1 结构体(Struct)的本质 **结构体是C语言中实现数据封装的基石,其核心特征在于内存独立性。每个成员变量在内存中按声明顺序依次排列,形成连续的
    发表于 04-08 09:18

    技术干货驿站 ▏深入理解C语言:嵌套循环与循环控制的底层原理

    多重循环,还是控制循环的执行流程,掌握这些知识都将为你的编程之路打下坚实的基础。嵌套循环在C语言中,循环语句可以嵌套使用,即在一循环中再使用另一循环。这种嵌套结
    的头像 发表于 02-21 18:26 1041次阅读
    技术干货驿站  ▏深入理解<b class='flag-5'>C</b><b class='flag-5'>语言</b>:嵌套循环与循环控制的底层原理

    分析C语言代码结构的设计问题

    来分析一C语言代码结构的设计问题。 这段代码,使用了两次malloc,分别给 p1 和 p2 申请了内存。用完后,内存释放,防止
    的头像 发表于 02-11 09:31 669次阅读

    EE-62:在C语言中访问短字内存

    电子发烧友网站提供《EE-62:在C语言中访问短字内存.pdf》资料免费下载
    发表于 01-07 14:02 0次下载
    EE-62:在<b class='flag-5'>C</b><b class='flag-5'>语言中</b>访问短字<b class='flag-5'>内存</b>

    EE-128:C语言中的DSP:从C调用汇编类成员函数

    电子发烧友网站提供《EE-128:C语言中的DSP:从C调用汇编类成员函数.pdf》资料免费下载
    发表于 01-07 13:48 0次下载
    EE-128:<b class='flag-5'>C</b><b class='flag-5'>语言中</b>的DSP:从<b class='flag-5'>C</b>调用汇编类成员函数