本文我将采用Linux环境测试C语言存储空间布局,以及采用VC6.0来测试static的常见用法。采用Linux环境来测试C语言存储空间布局,是因为Linux很容易利用shell命令中的size命令查看到进程存储区各段的大小。采用VC6.0来测试static的常见用法,是因为我们利用VC6.0很容易创建一个工程,该工程可以包含很多源文件,这样就很方便我们测试本文件与其他文件之间的关系了。

                  

不管是在Linux下C程序还是Windows下C程序,他们都是由正文段、数据段、BSS段、堆、栈等段构成的,只不过可能他们的各段分配地址不一样。Linux下的C程序正文段在低地址,而Windows下的C程序的正文段(代码段)在高地址。所有不用担心我用Linux环境和Windows环境共同测试带来不正确的数据。

一、C语言存储空间布局

C语言一直由下面部分组成:

正文段code segment/text segment,.text段):或称代码段,通常是用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读,某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。CPU执行的机器指令部分。

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

BSS段bss segment,.bss段):通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。

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

stack):栈又称堆栈,是用户存放程序临时创建的局部变量,也就是我们函数大括号"{}"中定义的变量(不包括static声明的变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且等调用结束后,函数的返回值也会被存放在回栈中。由于栈的先进先出特性,所有栈特别方便用来保存/恢复调用现场。从这个意义上讲,把堆栈看成一个寄存、交换临时数据的内存区。

【测试】:采用Linux环境测试

1、测试代码如下,文件名为progressStruct.c

保存后,输入gcc progressSturnct.c -o progressStruct编译生成二进制文件(可执行文件),然后输入size progressStruct查看进程progressStruct内存各段大小

text->正文段   data->数据段,存储已初始化全局变量段   bss->存储未初始化全局变量段  dec->以十进制显示总大小  hex->以十六进制显示总大小

2、修改progressStruct.c文件,修改后代码如下:

保存后,输入gcc progressSturnct.c -o progressStruct编译生成二进制文件(可执行文件),然后输入size progressStruct 查看进程progressStruct内存各段大小

3、继续修改progressStruct.c文件,修改后代码如下:

保存后,输入gcc progressSturnct.c -o progressStruct编译生成二进制文件(可执行文件),然后输入size progressStruct 查看进程progressStruct内存各段大小

4、3、继续修改progressStruct.c文件,修改后代码如下:

保存后,输入gcc progressSturnct.c -o progressStruct编译生成二进制文件(可执行文件),然后输入size progressStruct 查看进程progressStruct内存各段大小

其他非主函数中的变量存储在堆栈区

二、面向过程程序设计中的static

1、全局静态变量

在全局变量之前加上关键字static修饰,全局变量就被定义成一个全局静态变量

  1. 内存中的位置:静态存储器(静态存储区在整个程序运行期间都存在的)
  2. 初始化:未初始化的全局静态变量会被程序自动化为0
  3. 作用域:全局静态变量在声明它的文件之外是不可见,即其他文件不能使用被static修饰的变量。只能在从定义处到文件结尾中被使用。
【测试其作用域】:此测试利用VC6.0来完成
1、先测试不加static修饰全局变量,在另外一个文件来使用其他文件的全局变量
先在VC6.0上创建一个工程,命名为StaticTest,并在这个工程中创建两个.c文件,分别为a.c和main.c,对应代码如下:
运行结果如下:
2、现在修改a.c文件,修改后如下:
此时点击变成此工程,在编译过程没有报错误,而当我们去点击去链接这个工程的文件,此时就报错了,错误信息如下:
总结:被static修饰的全局变量(全局静态变量),不能被外部文件使用,只能被从定义开始到当前定义文件的结尾之间使用。

定义全局静态变量的好处:
<1>不会被其他文件所访问和修改。
<2>其他文件中可以使用相同名字的变量,不会发生冲突。

2、局部静态变量

在局部变量之前加上关键字static,局部变量被定义成为一个局部静态变量
  1. 内存中的位置:静态存储器
  2. 初始化:未经初始化的局部变量会被程序自动初始化为0
  3. 作用域:作用域仍为局部作用域,当定义它的函数或语句块结束的时候,作用域随之结束。
注:当static用来修饰局部变量的时候,它就改变了局部变量的存储位置,从原来的栈中存放改为静态存储区。但是局部静态变量在离开作用域之后,并没有被销毁,而是仍然驻留在内存当中(在其作用域外仍然可以定义相同名字的变量),直到程序结束,只不过我们不能再对他进行访问。当static用来修饰全局变量时候,它就改变了全局变量的作用域(在声明它的文件之外是不可见的),但是没有改变它的存放位置,还是在静态存储器中。

运行结果如下:

3、静态函数
在函数的返回类型前加上关键字static,函数就被定义成为静态函数。
函数的定义和声明默认情况下是extern的,但是静态函数只是在声明它的文件中可见,不能被其他文件所用,例如:
同样编译没有报错,而在链接时报错,错误提示找不到display()函数
定义静态函数的好处:
<1>其他文件中可以定义相同名字的函数,不会发生冲突
<2>静态函数不能被其他文件所用
存储说明符auto,register,extern,static,对应两种存储期:自动存储期和静态存储期。
auto和register对应自动存储期。具有自动存储期变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该块时撤销。关键字extern和static用来说明具有静态存储器的变量和函数,用static声明的局部变量具有静态存储持续期(static storage duration),或静态范围(static extent)。虽然他的值在函数调用之间保持有效,但是其名字的可视性仍限制在其局部域内。静态局部对象在程序执行到该对象的声明处时被首次初始化。
由于static变量的以上特性,可实现一些特定功能。
1、统计次数功能
声明函数的一个局部变量,并设置为static类型,作为一个计数器,这样函数每次被调用的时候就可以进行级数。这是统计函数被调用次数的做好的办法。因为这个变量是和函数息息相关的,二函数可能在不同的地方被调用,所以从调用者的角度来统计比较困难。代码如下:
运行结果如下:
从结果我们更加能证明:当static用来修饰局部变量的时候,它就改变了局部变量的存储位置,从原来的栈中存放改为静态存储区。但是局部静态变量在离开作用域之后,并没有被销毁,而是仍然驻留在内存当中(在其作用域外仍然可以定义相同名字的变量),直到程序结束,只不过我们不能再对他进行访问
总结:C语言程序可以看成一系列外部对象构成,这些外部对象可能是变量,也可能是函数。而内部变量是指定义在函数内部的函数参数及变量。外部变量定义在函数之外,因此可以在许多函数中使用。由于C语言不允许在一个函数中定义其它函数,因此函数本身只能是“外部”。由于C语言代码是以文件为单位来组织的,一个源程序所有源文件中,一个外部变量或函数只能在某个文件中定义一次,而其他文件通过extern声明来访问它(定义外部变量或函数的源文件中也可以包含对该外部变量的extern声明。)而static则可以限定变量或函数为静态存储。如果用static限定外部变量与函数,则可以将该对象的作用域限定为被编译源文件的剩余部分(从被定义处开始到文件末尾)。通过static限定外部对象,可以达到隐藏外部对象的目的。因而,static限定的变量或函数不会和同一程序中其他文件中同名的相冲突。如果用static限定内部变量,则该变量从程序一开始就拥有内存,不会随其所在函数的调用和退出而分配和消失。
C语言中使用静态函数的好处:
<1>静态函数会被自动分配在一个一直使用的存储器,直到退出应用程序实例,避免了调用函数时压栈出栈,这样速度就快得多。(常用函数可以选择使用static修饰)
<2>关键字"static",译成中文就是"静态的",所以内部函数又称静态函数(相对其他文件而言,被static修饰的函数,其他文件不能访问)。但此处"static"的含义不是指存储方式,而指对函数的作用域仅局限于本文件。
<3>使用内部函数的好处是:不同的人编写不同的函数时,不用担心自定定义的函数是否与其他文件中的函数同名。

C语言存储空间布局以及static详解相关推荐

  1. C语言存储空间布局以及static解析

    本文我将采用Linux环境测试C语言存储空间布局,以及采用VC6.0来测试static的常见用法.采用linux环境来测试c语言存储空间布局,是因为Linux很容易利用shell命令中的size命令查 ...

  2. 基于C语言的JPEG编码代码详解

    一.基于C语言的JPEG编码代码详解 #include <stdio.h> #include <stdlib.h> #include <string.h>#prag ...

  3. [免费专栏] Android安全之数据存储与数据安全「详解」

    也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 Android安全付费专栏长期更新,本篇最新内容请前往: [ ...

  4. java语言链栈_Java语言实现数据结构栈代码详解

    近来复习数据结构,自己动手实现了栈.栈是一种限制插入和删除只能在一个位置上的表.最基本的操作是进栈和出栈,因此,又被叫作"先进后出"表. 首先了解下栈的概念: 栈是限定仅在表头进行 ...

  5. c语言线性表库函数大全,数据结构(C语言版)-线性表习题详解

    <数据结构(C语言版)-线性表习题详解>由会员分享,可在线阅读,更多相关<数据结构(C语言版)-线性表习题详解(23页珍藏版)>请在人人文库网上搜索. 1.数 据 结 构 ,线 ...

  6. c语言 read 文件字节没超过数组大小时会怎样_剑指信奥 | C 语言之信奥试题详解(四)...

    趣乐博思剑指信奥系列 ❝ 趣乐博思剑指信奥系列,专门针对全国青少年信息学奥林匹克联赛 NOIP 而开展的专业教育方案.开设的课程有 C 语言基础,C++ 语言基础,算法设计入门与进阶,经典试题分析与详 ...

  7. C语言中指针与数组的区别,C语言 指针与数组的详解及区别

    C语言 指针与数组的详解及对比 通俗理解数组指针和指针数组 数组指针: eg:int( *arr)[10]; 数组指针通俗理解就是这个数组作为指针,指向某一个变量. 指针数组: eg:int*arr[ ...

  8. gets和fgets函数及其区别,C语言gets和fgets函数详解

    gets和fgets函数及其区别,C语言gets和fgets函数详解 每当讨论 gets 函数时,大家不由自主地就会想起 1988 年的"互联网蠕虫",它在 UNIX 操作系统的 ...

  9. Android 进阶——Framework 核心之Android Storage Access Framework(SAF)存储访问框架机制详解(二)

    文章大纲 引言 一.DirectFragment 1.当选中DirectoryFragment中RecyclerView的Item时 2.选中DirectoryFragment中RecyclerVie ...

最新文章

  1. Programming Computer Vision with Python (学习笔记四)
  2. 对 Stream 中 Map 与 ForEach 做个简单说明
  3. spring(1)Spring之旅
  4. 数字通信系统的主要性能指标
  5. Asp.net MVC 3实例学习之ExtShop(一)————创建应用并设置开发环境
  6. linux xargs命令
  7. GCD 深入理解(一)
  8. 教育期刊《英语广场》期刊简介及投稿须知
  9. Lenovo ServerGuide 10.4
  10. jacob调用word宏
  11. 神仙工具!百度网盘资源一键转存阿里云盘,YYDS
  12. 网络安全-DoS与DDoS攻击原理(TCP、UDP、CC攻击等)与防御
  13. 进程管理软件SysCheck使用指南
  14. Android Banner图片轮播
  15. 第一次写正规论文的同学务必分享,排版自动排版,加注释。。。。。。等等!!!!!!!!(copy也得整出档次来啊,这就是门面啊)
  16. mysql vsize_Oracle 中的Userenv()
  17. golang学习笔记
  18. 计算机近几年自考本科题,近几年自考管理系统中计算机硬应用题汇总.doc
  19. 03-OSPF OE2和OE1外部路由详解
  20. Android 指南针

热门文章

  1. VR 中的 3 DoF 与 ​​6 DoF是什么 ?
  2. pandas 讲清楚pivot_table和margins
  3. python写一个笔记软件_程序员们都用什么记笔记软件?
  4. 乐里斗未能链接服务器,LOONEY TUNES 反斗世界无法连接服务器是什么原因
  5. sysprep封装win7不用虚拟机_Win7封装经验总结
  6. myeclipse 2017 ci 10 破解包+教程(亲测已成功)
  7. ubuntu 安装amarok音乐播放器
  8. 大道无形 难以揣摩的苹果商店审核制度
  9. 域格4G网优模块获取
  10. windows11 文件夹打开慢解决方法推荐