C++:关键字:Static使用详解

要想搞清关键字static 的使用方法,必须先搞清楚,可执行程序段的分类以及各段在内存区的逻辑地址映射

1:可执行程序内存分配

一个程序的3个基本段:text段,data段,bss段。

1.1 BSS(Block Started by Symbol) 

通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。

特点:可读写,在程序执行之前BSS段会自动清零。

所以:未初始化的全局变量在程序执行之前已经是零。

请注意和数据段的区别:BSS存放的是未初始化的全局变量和静态变量,数据段存放的是初始化后的全局变量和静态变量。

1.2:数据段data存放在编译阶段(而非运行时)就能确定的数据,可读可写

也就是说通常所说的静态存储区,赋了初值的全局变量和赋初值的静态变量存放在这个区域,常量也存在这个区域。数据段,代码段在程序运行之前就已经确定了

1.3:代码段text:通常是指用来存放程序执行代码的一块内存区域

这部分区域的大小在程序运行之前就已经确定,并且内存区域通常属于只读,缪谢架构也运行代码段可写,允许自修改程序。

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

text段在编译时确定,内存中被映射为只读,但data段和bss段是可写的。

2:C++语言五大内存分区(语言逻辑地址)

2.1 栈区(堆栈区Stack)

堆栈是由编译器自动分配释放,存放函数的参数和局部变量的值(auto类型),操作方式类似于数据结构中的栈。栈的申请是由系统自动分配,如在函数内部申请一个局部变量 int a,同时判断所申请空间是否小于栈的剩余空间,如果小于则为其开辟空间,为程序提供内存,否则将报异常提示栈溢出。

2.2 堆(heap)

堆一般有程序员分配释放,若程序员不释放,程序结束可能由OS回收。

但是它与数据结构中的堆是两回事,分配方式类似于链表,申请是由程序员自己操作使用 malloc或者new.

申请过程是比较复杂的,当系统收到程序的申请时,会遍历记录空闲内存地址的链表,以求寻找第一个空间大于所申请空间的堆节点,然后将节点从空闲节点链表中删除,并将该节点的空间分配给程序,有些情况下,新申请的内存块的首地址记录本次分配的内存块大小,这样在free()时能正确的释放内存空间。

2.3:全局静态存储区

全局静态存储区与静态变量的存储是放在一起的,初始化的全局变量与静态变量存放在一块区域,(data区)未初始化的全局变量与未初始化的静态变量存放在相邻的另一款区域(BSS区)

2.4:文字常量区

常量字符串存放在全局静态存储区,程序结束后由系统释放。

2.5:程序代码区

存放程序的二进制代码区

 这两者的区别就是:代码段,数据段,堆栈段是cpu级别的概念,五大分区属于语言级别的概念,两者是不同的概念。

3:可执行程序内存空间与逻辑地址的映射与划分

 左边是UNIX系统的执行文件,右边是进程对应的逻辑地址空间的划分情况

二:static变量 

static变量主要区分静态全局变量和全局变量、局部变量和静态局部变量之前的区别。

2.1 :静态全局变量、全局变量

静态全局变量、全局变量的区别主要通过生存周期和作用域来区分

全局变量静态全局变量
生存周期程序运行开始到程序结束程序运行开始到程序结束
作用域所有代码只用当前文件可以访问
代码段中位置全局数据区全局数据区
  1. 静态全局变量和全局变量均存放在数据段data中
  2. 静态局部变量在函数内定义,生存周期为整个源程序,但作用域与自动变量相同,只能在定义该变量的函数内使用。退出函数后,尽管该变量还继续存在,但不能使用它。
  3. 对基本类型的静态局部变量若在说明时未赋初值,则系统自动赋值为零,而对自动变量不赋初值,其值是不定的。
  4. 全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式,但是他们的作用域不同:非静态全局变量的作用域是整个源程序(多个源文件可以共同使用),而静态全局变量则限制了其作用域,即只在定义该变量的源文件有效,在同一源程序的其他源文件是不能使用的。

实作

1:全局变量:由编译结果可知,文件a.c可以访问到b.c文件中的静态全局变量b。 

2: 静态全局实例 :由编译结果可知,文件a.c无法访问到b.c文件中的静态全局变量b,所以编译报错。

 

 2.2 静态局部变量、局部变量

静态局部变量、局部变量的区别主要通过生存周期和作用域来区别

局部变量静态局部变量
生存周期函数调用开始到函数返回程序运行开始到程序运行结束
作用域函数内部函数内部
代码段中位置全局数据区
  1. 静态局部变量存放在数据段 data中,局部变量存放在栈中,静态局部变量和局部变量都只能在函数内部才可以访问。
  2. 函数每次访问静态局部变量,该变量的值为最后一次访问修改后的值

实作

3:静态函数 

  1. 在函数的返回类型前加上关键字 static,函数就被定义为静态函数。
  2. 函数的定义和声明默认情况下是 extern,但是静态函数却只是在声明它的文件中可见,不能被其他文件所用。
  3. static 函数(也叫内部函数)它只能被本文件中的函数调用,而不能被同一程序其他文件中的 函数调用。
  4. 区别于一般的非静态函数(外部函数)static在C++里面可以用来修饰变量,也可以用来修饰函数
  5. 我们先看下修饰变量时,变量在C++里面可存在全局数据区,栈,堆。

3.1 定义静态函数的好处

  1. 其他文件中可以定义相同名字的函数,不会发生冲突,不用担心自己定义的函数,是否会与其他文件中的函数同名,因为即使同名也没什么关系。
  2. 静态函数不能被其他文件所用,存储说明符:auto、register、extern、static,只是对应两种存储期:自动存储期和静态存储期。
  3. 统计次数功能:声明函数的一个局部变量,并设为static类型,作为一个计数器,这样函数每次被调用的时候就可以进行计数统计。这是统计函数调用次数最好的一个办法,因为这个变量时和函数调用息息相关,如果从调用者的角度统计,是非常困难的。
  4. 静态函数会被自动分配在一个一直使用的存储区,知道退出应用程序实例,避免调用函数时压栈出栈,速度会快很多。

 4: 一个关于static变量的巧妙用法----偷梁换柱

如何定义一个和库函数名一样的函数,并在函数中调用该库函数?

 粉丝提问|c语言:如何定义一个和库函数名一样的函数,并在函数中调用该库函数

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值