C语言内存模型

内存模型——屏蔽各个硬件平台和操作系统的内存访问差异,以实现让xxx程序在各种平台下都能达到一致的内存访问效果。(即不同平台下的实现差别被统一的内存模型所隐藏,只需要根据这个抽象的内存模型来编写程序即可)。

不同语言有不同的内存模型,只有掌握了内存模型,才算是真正具有了对程序的时间和空间效率进行分析的基本能力。不难看出,内存模型其实定义了变量的一套访问规则。下面介绍C语言在linux下的内存模型。
这里写图片描述
在C语言中编译的进程中,内存一般分为四个段:

  • 栈(Stack):编译器分配自动清除。
  • 堆(Heap):人为申请、释放。程序结束后OS会回收。
  • 全局/静态存储区(BSS & Data segment):其中BSS段包含未初始化全局/静态变量(自动以0赋值), Data段包含初始化全局/静态变量。
  • 代码存储区(Text segment):正常情况下只读(readOnly)。包含代码和常量。

1.存储类型(Storage Class)
c语言中的存储类型有auto, extern, register, static 四种,存储类型说明了该变量要在进程的哪一个段中分配内存空间。

  • auto存储类型
    auto只能用来标识局部变量的存储类型,对于局部变量,auto是默认的存储类型,不需要显示的指定。因此,auto标识的变量存储在栈区中。
  • extern存储类型
    extern用来声明在当前文件中引用在当前项目中的其它文件中定义的全局变量。如果全局变量未被初始化,那么将被存在BBS区中,且在编译时,自动将其值赋值为0,如果已经被初始化,那么就被存在data区中。
  • register存储类型
    声明为register的变量在由内存调入到CPU寄存器后,则常驻在CPU的寄存器中,因此访问register变量将在很大程度上提高效率,因为省去了变量由内存调入到寄存器过程中的好几个指令周期。
  • static存储类型
    被声明为静态类型的变量,无论是全局的还是局部的,都存储在全局/静态存储区中。其生命周期为整个程序,如果是静态局部变量,其作用域为一对{}内,如果是静态全局变量,其作用域为当前文件。静态变量如果没有被初始化,则自动初始化为0。静态变量只能够初始化一次。

2.作用域(scope)
C语言中变量的作用域有3种:代码块作用域,文件作用域,原型作用域。

  • 代码块作用域
    位于一堆花括号之间的所有语句是代码块,在代码块的开始位置声明的标识符的作用域就是代码块作用域。从声明开始,到所处的最小的右大画括号结束。
  • 文件作用域
    任何在代码块之外声明的标识符的作用域是文件作用域。从声明开始,到文件结尾结束。
  • 原型作用域
    在函数原型中声明的标识符的作用域是原型作用域。从声明开始,到有小括号结束。(只是函数原型声明时,定义时的形参属于代码块作用域)。

3.生命周期
全局变量和静态变量是在程序编译期就分配到data段或bss段中的,在整个程序的运行期,data段和bss段中的内容是不会发生改变的。所以所有的全局变量和静态变量的生命周期必定是从程序编译到程序运行结束。而且如果全局变量和静态变量没有初始化,会统一默认初始化为0.
而局部变量是在程序的运行时,在栈中分配的内存,所以生命周期一定是从程序运行的某一个时刻开始。

4.链接属性(linkage)
C语言的编译是对每个文件单独进行的,然后将所有编译过的二进制文件链接成一个可执行文件。那么当多个源文件都出现同一个标识符时该怎么办呢?这就涉及到标识符的链接属性。链接属性分为三种:外部(external)、内部(internal)、无(None)。

  • 外部链接属性
    在文件A中具有external链接属性的变量(或函数名)具有全局可见性,对于变量,在声明前加extern表示引用文件A中的对应变量,函数则可以直接使用。
  • 内部链接属性
    internal属性出现在static修饰之后。当具有external属性的变量(或函数名)用static关键字修饰之后,就具有了internal链接属性,其他文件不能访问它们。
  • None链接属性
    缺省情况下,除了上述说明的external属性和internal属性以外,其余均为none。函数形式参数和代码块内声明的变量在缺省情况下具有none链接属性 。none链接属性标识符仅允许作用域内访问。static只能修改external属性的标识符,若修饰none属性的,改变的是存储类型而非链接属性。
    (链接属性不仅意味着能不能访问变量,也意味着能不能在文件中定义同名变量或函数名。)

Notice:这四个属性互相之间有联系,某些关键字可能同时涉及多个属性,比如static关键字就涉及到了变量的作用域、链接属性、生存周期和存储类型。

这里写图片描述

猜你喜欢

转载自blog.csdn.net/u013608424/article/details/80190871