通解C/C++静态关键字static在变量、函数中的作用,傻傻分不清楚!

Author: Nirvana Of Phoenixl
Proverbs for you:There is no doubt that good things will always come, and when it comes late, it can be a surprise.

  首先在讲解static关键字之前先明确几个一定需要知道的概念,并且在使用过程当中实际上许多人并不会去注意这些内容的细节,这些东西必须明确。

1 关于变量(作用域):

  在函数或块内部的局部变量;在所有函数外部的全局变量;在形式参数的函数参数定义中每一个变量都有其有效的作用范围,这也就是变量的作用域,所谓作用域就是在该变量的能够发挥作用的范围之外,程序是不能访问的。变量按照作用域可以分为全局变量和局部变量,这也是我们常常听到的概念。那么到底什么是全局变量什么是局部变量呢?

(1)局部变量:

  在一个函数内部定义的变量是内部变量,它只在本函数的范围内有效,也就是说定义的该变量只能在本函数内部使用,在此函数外部是无法使用的。这取决于它是如何存储的,这个后面会讲到。举个栗子

#include <stdio.h>
Function1 (int a)        //形参也是局部变量:形参出现在函数声明处,作用范围只能是本行的括号。
{
	/*fun函数局部变量:只能在function1函数中使用*/
	int d;
	int e;}
 int main () 
{ 
/* main局部变量声明 :只能在main函数内使用*/ 
int a, b; 
int c;return 0; 

}

注意:主函数定义的a、b、c也只在主函数内有效,并不会因为主函数中定义而在整个文件或者程序中有效,主函数也不能使用其他函数中定义的变量。形参也是局部变量即函数function(int
a)中的a也是局部变量。

(2)全局变量

  在函数之外定义的变量称为全局变量,全局变量的作用范围是从定义变量的位置开始到本程序结束举个栗子

#include <stdio.h> 
 int g; /* 全局变量声明 :此行以下可以使用全局变量g,但是在g1,g2之前的函数不能使用全局变量g1,g2*/
fun()
{
  int c,d;
}

Int g1,g2; /*全局变量声明:从此行开始以下均可以使用全局变量g, g1,g2,*/
 int main () 
{
  int a, b; /* 局部变量声明 */return 0;
 }

注意:在程序中,局部变量和全局变量的名称可以相同,但是在函数内,如果两个名字相同,会使用局部变量值,全局变量不会被使用。全局变量作用是增加函数间数据的联系渠道,同一个文件中所有函数均能使用全局变量,因此牵一发则动全身,所以非必要不使用全局变量,会降低函数通用性、清晰性,同一个源文件中全局变量与局部变量同名,则在局部变量的作用范围内自动屏蔽全局变量

2 关于变量存储(存储期)

  上述了变量的作用域,下面理解分析一下变量的存储期,可以理解为变量的生命周期,这主要由变量的存储决定,因此也称为存储期。所谓存储期显而易见的是从时间角度来分析的。通常可以将存储分为静态存储和动态存储。所谓静态存储是指程序在运行期间,系统自动分配的固定的存储空间;动态存储为运行期间系统对变量动态的分配存储空间。按照不同存储可以将存储空间分为:
  程序区:即存放程序代码的位置,存放函数体的二进制代码,由操作系统进行管理的
  全局区:用于存放全局变量和静态变量以及常量(静态存储区)
  栈区:由编译器自动分配释放, 存放函数的参数值,局部变量等(动态存储区)
  堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收(new~delete(C++),malloc ~ free(C))。
  【注意】可以看到实际上全局变量和局部变量的本质区别就在这里,全局变量保存在内存的全局存储区中,占用静态的存储单元局部变量保存在栈中,只有在所在函数被调用时才动态地为变量分配存储单元

3 利用static修饰变量和函数

   静态修饰关键字,主要分两个方面修饰变量和修饰函数,用static修饰的变量称为静态变量,函数称可称为静态函数。那前面说变量又可以分为全局和局部变量,则再次细分一下就可以分为静态全局变量和静态局部变量,先不用乱,其实全局与局部的性质不变只是在加上静态的理解就可以啦。

3.1 static修饰变量时:

3.1.1 用static修饰静态局部变量:

  原来我们说局部变量在函数内使用,并且调用完该函数,局部变量自动释放内存,而为了保证含有该局部静态变量的函数在调用结束后,该变量值不释放而是保留原值,就要使用到static来修饰。
   静态局部变量赋初值是在编译时进行的,即只赋一次初值,每次调用函数时不在重新赋初值而是保留上次函数调用结束时的值。(而普通的局部变量赋初值是在运行时候,而不是编译时候,每次调用相当于重新赋值了),有兴趣可以去看一下利用static修饰变量完成阶乘。
  注意:有个误区就是,这里说的静态指局部变量的值不被释放,下次可以继续使用上次的值,而不是说该局部变量不能被修改,注意静态的概念它和常量const不同。
举个栗子:比如定义了一个add函数,这个函数作用是将两个自加整型值加起来,其中有一个普通局部变量b = 1 和一个静态局部变量a = 1,那么在调用此函数的过程当中,b会在每次调用运行时被初始化为当前值1;而静态变量a只在第一编译的时候有初值1,则而调用的时候每次都是自加1在此基础上一直自加。

3.1.2 用static修饰静态全局变量:

  保证此全局变量只能被本文件引用,而不能被其他文件引用,即使使用extern外部声明也不可以访问,这样一来其他文件也可以定义相同名字的变量而不会发生冲突。
   注意:不使用static的全局变量,其默认是有外部链接属性的,作用域是整个工程文件(包含很多源文件.c/.cpp等),在一个文件内定义的全局变量在另一个文件中,可通过extern全局变量名的声明就可以使用。使用static声明的全局静态变量作用域是所在的文件(如.c),其他文件即使使用extern声明也不能使用。

需要注意:不要误认为用static声明的外部变量(全局变量)才能采用静态存储的方式(存放在静态存储区中)而不加static的是动态存储(存放在动态存储区中),前面已经讲过了普通全局变量也采用静态存储方式,只是静态全局和普通全局变量的作用范围不同而已,两者都是在编译时分配的内存

3.2 static修饰函数时:

  static同样可以修饰函数,函数本质上时全局的也就是说,任何一个函数都可以被其他函数调用,这也是函数灵活使用的本质,但是通常也可以指定函数是只能在文件中调用,还是可以在其他文件调用。根据函数是否能被其他源文件调用,可以将函数分为内部函数和外部函数。

3.2.1 使用static修饰的函数

  显而易见,使用static修饰的函数称为内部函数:如果一个函数只能被本文件的其他函数调用,比如也就是同一个.c文件中的其他函数调用,而不能利用其源文件调用则称为内部函数。该函数的定义如下:

static int fun(int q,int p) //static 函数类型标识  函数名(函数参数)

  将函数使用限定在本文件内,如果其他文件有相同名字的函数或不干扰,使得该函数局部化。

3.2.2 不使用static修饰的函数:

  在定义函数的时候,如果函数首部使用extern关键字,则标识该函数是外部函数,可以供其他文件调用。(注意如果省略不屑,则也默认是外部函数)

关于extern、const后面会讲解,拙见仅参考
在这里插入图片描述

  • 14
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值