C语言的重要知识点☞static关键字
static译为"静态的",该关键字可以修饰以下内容:
- 修饰局部变量
- 修饰全局变量
- 修饰函数
在讲解static的具体作用前需要先知道"作用域"以及"生命周期"的概念:
作用域:
作用域是一个程序设计概念,通常来说,一段程序代码中用到的名字并不总是有效的(可用)的,而限定这个名字的可用性的代码范围就是这个名字的作用域
大白话讲就是:这个东西在哪块地方可以使用,它的作用域就在哪儿
举个例子:
#include<stdio.h>
void f()
{int tmp=0;tmp++;// 在作用域内有效,可用对其进行操作
}
int main()
{tmp++;// 报错,tmp的作用域只在f函数的范围内,出了作用域就不可用了return 0;
}
作用域范围:
- 局部变量的作用域是变量所在的局部范围(如上面例子中的tmp变量)
- 全局变量的作用域是整个工程(项目)
举一个全局变量的例子:
#include<stdio.h>int a = 0;// 定义在全局
// a = 10;// 全局作用域不能进行赋值语句
void f()
{a = 10;// 可以在任意函数中访问
}
int main()
{f();a++;// 可以在任意函数中访问printf("%d", a);return 0;
}
额外补充一个知识点:C 语言规定,在全局作用域只能进行变量定义和初始化,不能直接执行语句(如 a++;a=10
)。
生命周期:
生命周期指的是变量的创建(申请内存空间)到 变量的销毁(收回内存空间)之间的一个时间段
联系前面说到的作用域,我们知道作用域限定了变量的可用/有效范围,不难想到从本质上看其实就是出了作用域变量就被销毁了,所以就不可用即无效了
生命周期时间段:
- 局部变量的生命周期是:进入作用域变量创建,生命周期开始,出作用域生命周期结束
- 全局变量的生命周期是:整个程序的生命周期
static关键字的作用:
①static修饰局部变量会改变局部变量的生命周期,生命周期会和程序的生命周期一样
来看两段代码:
从上面两段代码的结果不难看出,变量 i 的生命周期在被static修饰后明显发生了改变,原先的生命周期(如代码1所示)只在test()函数中,故每次调用test()函数,就会重新创建一次变量 i ,因为 i 出了函数(作用域)销毁了,所以每次打印的值都是1
但是被static修饰后,打印的结果是累加的,也就是变量 i 的值没有在中途销毁过,也就是出了函数没有被销毁,故重新进入函数就不会重新创建变量 i ,直接用上一次的值进行运算
为什么会这样呢?
因为static修饰变量后,本质上改变了变量的存储类型,本来一个局部变量是存储在内存的"栈区"
但是被static修饰后存储到了静态区,存储在静态区的变量和全局变量是一样的,生命周期就和程序的生命周期一样了,只有程序结束,变量才销毁,内存才回收。但是作用域不变哦
使用建议:未来一个变量出了函数以后,还想保留值,等下次进入函数继续使用,就可以用static关键字修饰
②static修饰全局变量会使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用
extern关键字用于声明外部符号,如果一个全局的符号在A文件中被定义,在B文件中想被使用,就可以使用extern关键字进行声明,然后就可以使用了
上面的代码,左边的可以正常运行,但是右边的代码编译时会出现链接性错误
这就是static修饰后,使得这个全局变量只能在本源文件中使用,不能在其他源文件使用
为什么会这样呢?
本质原因是全局变量默认是具有外部链接属性的,在外部文件中想要使用,只要适当的声明就可以使用;但是全局变量被static修饰后,外部链接属性就变成了内部链接属性,只能在自己所在的源文件内部使用了,其他源文件,即使声明了,也是无法正常使用的
使用建议:如果一个全局变量,只想在所在的源文件内部使用,不想被其他文件发现,就可以使用static修饰
③static修饰函数,和static修饰全局变量的效果是一样的
一个函数在整个工程中都可以使用,如果想在外部源文件使用,一样的加上extern关键字修饰并且在另一个文件中声明就可以了
但是一旦被static关键字修饰后,就只能在本文件内部使用,其他文件无法正常的链接使用了
本质原因也是函数默认具有外部链接属性,具有外部链接属性,使得函数在整个工程中只要适当声明就可以被使用。但是被static修饰后变成了内部链接属性,使得函数只能在自己所在的源文件内部使用
使用建议:如果一个函数,只想在所在的源文件内部使用,不想被其他文件发现,就可以使用static修饰
完