C语言编程程序的存储类别

描述

在c语言中,每个变量和函数有两个属性:数据类型和数据的存储类别。

C语言中局部变量和全局变量变量的存储类别(static,extern,auto,register)

一. 从变量的作用域划分变量(即从空间)角度来分

1.全局变量

2.局部变量

二. 从变量值存在的时间或存储类别(即生存期)角度来分

2.1. 静态存储区

存放以下数据: 代码段(text)、只读数据段(rodata)、读写数据段(rwdata)、未初始化数据段(bbs)

静态存储区存放全部的全局变量, 这些变量将在链接之后产生, 程序执行完毕就释放, 程序执行的过程中它们占据固定的存储单元, 而不会动态的进行分配和释放

2.2. 动态存储区

存放以下数据: 函数形参、自动变量(未加static声明的局部变量)、函数调用时的现场保护和返回地址

对以上这些数据,在函数开始调用时分配动态存储空间,函数结束时释放这些空间。

三. 从用户内存空间角度分为三个部分

1. 程序区

C语言


2. 静态存储区

3. 动态存储区

4. 从C程序运行时又可分为以下存储区

1. 代码段 (Code | Text)

代码段由程序中执行的机器代码组成。在C语言中,程序语句进行编译后,形成机器代码。在执行程序的过程中,CPU的程序计数器指向代码段的每一条机器代码,并由处理器依次运行。

2. 只读数据段(ROData)

2.1 ROData介绍

只读数据段是程序使用的一些不会被更改的数据,使用这些数据的方式类似查表式的操作,由于这些变量不需要更改,因此只需要放置在只读存储器中即可。只读数据段由程序中所使用的数据产生,该部分数据的特点是在运行中不需要改变,因此编译器会将该数据段放入只读的部分中。C语言中的只读全局变量,只读局部变量,程序中使用的常量等会在编译时被放入到只读数据区。 注意:定义全局变量const char a[100]={“ABCDEFG”};将生成大小为100个字节的只读数据区,并使用“ABCDEFG”初始化。如果定义为:const char a[ ]={“ABCDEFG”};则根据字符串长度生成8个字节的只读数据段(还有’’),所以在只读数据段中,一般都需要做完全的初始化。

2.2 Example

C语言

3. 已初始化读写数据段(RW data)

3.1 RWData介绍

已初始化数据是在程序中声明,并且具有初值的变量,这些变量需要占用存储器的空间,在程序执行时它们需要位于可读写的内存区域内,并具有初值,以供程序运行时读写。全局变量全部存放在静态存储区,在程序开始执行时给全局变量分配存储区,程序行完毕就释放。在程序执行过程中它们占据固定的存储单元,而不动态地进行分配和释放;

全局变量

静态(static) 局部变量

3.2 Example

C语言

4. 未初始化数据段(BSS)

4.1 BSS介绍

未初始化数据是在程序中声明,但是没有初始化的变量,这些变量在程序运行之前不需要占用存储器的空间。

4.1 Example

C语言

5. 堆(heap)

5.1 堆空间介绍

堆内存只在程序运行时出现,一般由程序员分配和释放。
在具有操作系统的情况下,如果程序没有释放,操作系统可能在程序(例如一个进程)结束后回收内存。

5.2 Example

C语言

6. 栈(stack)

6.1 栈空间介绍

栈内存只在程序运行时出现,在函数内部使用的变量、函数的参数以及返回值将使用栈空间, 栈空间由编译器自动分配和释放。 栈空间是动态开辟与回收的。在函数调用过程中,如果函数调用的层次比较多,所需要的栈空间也逐渐加大 对于参数的传递和返回值,如果使用较大的结构体,在使用的栈空间也会比较大。

6.2 栈区主要用于以下数据的存储

函数内部的动态变量 函数的参数 函数的返回值

6.3 Example

C语言

5. 4种局部变量和全局变量的存储类别(static, extern, auto, register)

5.1 Static

有时希望函数中的局部变量的值在函数调用结束后不消失而保留原值,这时就应该指定局部变量为“静态局部变量”,用关键字static进行声明。

C语言

对静态局部变量的说明:

1)静态局部变量属于静态存储类别,在静态存储区内分配存储单元。在程序整个运行期间都不释放。而自动变量(即动态局部变量)属于动态存储类别,占动态存储空间,函数调用结束后即释放。
2)静态局部变量在编译时赋初值,即只赋初值一次;而对自动变量赋初值是在函数调用时进行,每调用一次函数重新给一次初值,相当于执行一次赋值语句。
3)如果在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋初值0(对数值型变量)或空字符(对字符变量)。而对自动变量来说,如果不赋初值则它的值是一个不确定的值。

5.2 Extern

外部变量(即全局变量)是在函数的外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件终了。如果在定义点之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量作“外部变量声明”。表示该变量是一个已经定义的外部变量。有了此声明,就可以从“声明”处起,合法地使用该外部变量。

C语言

说明:

在本程序文件的最后1行定义了外部变量A,B,但由于外部变量定义的位置在函数main之后,因此本来在main函数中不能引用外部变量A,B。现在我们在main函数中用extern对A和B进行“外部变量声明”,就可以从“声明”处起,合法地使用该外部变量A和B。

5.3 Auto

函数中的局部变量,如不专门声明为static存储类别,都是动态地分配存储空间的,数据存储在动态存储区中。函数中的形参和在函数中定义的变量(包括在复合语句中定义的变量),都属此类,在调用该函数时系统会给它们分配存储空间,在函数调用结束时就自动释放这些存储空间。这类局部变量称为自动变量。自动变量用关键字auto作存储类别的声明。

C语言

a是形参,b,c是自动变量,对c赋初值3。执行完f函数后,自动释放a,b,c所占的存储单元。
关键字auto可以省略,auto不写则隐含定为“自动存储类别”,属于动态存储方式。占用栈空间

5.4 Register

为了提高效率,C语言允许将局部变量得值放在CPU中的寄存器中,这种变量叫“寄存器变量”,用关键字register作声明。

C语言

说明:

1) 只有局部自动变量和形式参数可以作为寄存器变量;
2)一个计算机系统中的寄存器数目有限,不能定义任意多个寄存器变量;
3)局部静态变量不能定义为寄存器变量。

6. 总结

从变量的作用域(即从空间)角度来分,可以分为全局变量和局部变量。从变量值存在的作时间(即生存期)角度来分,可以分为静态存储方式和动态存储方式。

代码段、只读数据段、读写数据段、未初始化数据段属于静态区域

静态区域: 是指在程序运行期间分配固定的存储空间的方式

堆和栈属于动态区域

动态区域: 是在程序运行期间根据需要进行动态的分配存储空间的方式。

代码段、只读数据段 和 读写数据段 将在链接之后产生

未初始化数据段将在程序初始化的时候开辟 而堆和栈将在程序的运行中分配和释放。C语言程序分为映像和运行时两种状态。在编译-连接后形成的映像中,将只包含代码段(Text)、只读数据段(RO Data)和读写数据段(RW Data)。在程序运行之前,将动态生成未初始化数据段(BSS) 在程序的运行时还将动态形成堆(Heap)区域和栈(Stack)区域。一般来说,在静态的映像文件中,各个部分称之为节(Section),而在运行时的各个部分称之为段(Segment)。如果不详细区分,可以统称为段。C语言在编译和连接后,将生成代码段(Text)、只读数据段(RO Data)和读写数据段(RW Data)。在运行时,除了以上三个区域外,还包括未初始化数据段(BSS)区域和堆(Heap)区域和栈(Stack)区域。

7. 一些实例


责任编辑人:CC

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

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分