C语言-学习之路-07

内存管理
作用域

C语言中变量的作用域可分为:代码作用域、函数作用域、文件作用域

局部变量

局部变量也叫auto自动变量,一般情况下代码块{}内部定义的变量都是自动变量,它有如下特点:

  • 在一个函数内定义,只在函数范围内有效
  • 在复合语句中定义,只在函数范围内有效
  • 随着函数调用的结束或复合语句的结束局部变量的声明周期也随即结束
  • 如果没有赋初值,内容为随机
静态(static)局部变量
  • static局部变量的作用域也是在定义的函数内有效
  • static局部变量的生命周期和程序运行周期一样,同时static局部变量的值只初始化一次,但可以赋值多次。
  • static局部变量若未赋以初值,则由系统自动赋值:数值型变量自动赋初值0,字符型变量赋空值。
全局变量
  • 在函数外定义,可被本文件及其它文件中的函数所共用,若其它文件中的函数调用此变量,须用extern声明。
  • 全局变量的生命周期和程序运行周期一样。
  • 不同文件的全局变量不可重名。
extern全局变量声明

extern int a; 声明一个变量,这个变量在别的文件中已经定义了,这里只是声明,而不是定义。

全局函数和静态函数

在C语言中,函数都是默认全局的,使用关键字static可以将函数声明为静态,函数定义为static就意味这个函数的文件中使用,在其他文件中不能调用,即使在其他文件中声明这个函数都没用。
对于不同文件中的static函数名字可以相同。
注意
允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰。
同一源文件中,允许全局变量和局部变量同名,在局部变量的作用域内,全局变量不起作用。
所有的函数默认都是全局的,以为着所有的函数都不能重名,但如果是static函数,那么作用域是文件级的,所以不同的文件static函数名可以是相同的。

类型 作用域 声明周期
auto变量 一对 { }内 当前函数
static局部变量 一对 { }内 整个程序运行期
extern变量 整个程序 整个程序运行期
static全局变量 当前文件 整个程序运行期
extern函数 整个程序 整个程序运行期
static函数 当前文件 整个程序运行期
register变量 一对 { }内 当前函数
内存分布
内存分区

C程序代码经过预处理、编译、汇编、链接4步后生成一个可执行程序。
在Linux下,程序是一个普通的可执行文件。在没有运行程序前,即程序没有加载到内存前,可执行程序内部已经分为3段信息,分别为代码区(text)、数据区(data)和未初始化数据区(bss)。

  • 代码区
    存放CPU执行的机器指令。通常代码区可是共享的(即另外的执行程序可以调用它),使其可共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可。代码区通常是只读的,使其只读的原因是防止程序意外地修改了它的指令。另外,代码区还规划了局部变量的相关信息。
  • 全局初始化数据区/静态数据区(data)段
    该区包含了在程序中明确被初始化的全局变量、已经初始化的静态变量(包括全局静态变量和局部静态变量)和常量数据(如字符串常量)。
  • 未初始化数据区(bss区)
    存入的是全局未初始化变量和未初始化静态变量。未初始化数据区的数据在程序开始执行之前被内核初始化为0或者为空NULL。

程序在加载到内存前,代码区和全局区(data和bss)的大小就是固定的,程序运行期间不能改变。然后,运行可执行程序,系统把程序加载到内存,除了根据可执行程序的信息分出代码区(text)、数据取(data)、和未初始化数据区(bss)之外,还额外增加了栈区、堆区。
在这里插入图片描述

  • 代码区(text segment)
    加载的是可执行文件代码段,所有的可执行代码都加载到代码区,这块内存是不可以在运行期间修改的。
  • 未初始化数据区(BSS)
    加载的是可执行文件BSS段,位置可以分开亦可以紧靠数据段,存储于数据段的数据(全局未初始化,静态未初始化数据)的生存周期为整个程序运行过程。
  • 全局初始化区/静态数据区(data segment)
    加载的是可执行文件数据段,存储于数据段(全局初始化,静态初始化数据,文字常量(只读))的数据的生存周期为整个程序运行过程。
  • 栈区(stack)
    栈是一种先进后出的内存结构,由编译器自动分配释放,存放函数的参数值、返回值、局部变量等。在程序运行过程中实时加载和释放。因此,局部变量的生存周期为申请到释放该段栈空间。
  • 堆区(heap)
    堆是一个大容器,它的容量要远远大于栈,但没有栈那样先进后出的顺序。用于动态内存分配。堆在内存中位于BSS区和栈区之间。一般由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。

猜你喜欢

转载自blog.csdn.net/weixin_50918736/article/details/130545147