前言
static关键字非常好用,特别是早期时候,对于C语言来说,就是靠static关键字完成封装性滴;常见的大型项目中,static用得非常多,并且static关键字也是面试时候的热门关键字之一。在C++中static关键字由于多了类,所以会在C语言的基础上扩展了一些关于类中成员用static关键字修饰的所以掌握非常重要。
文章目录
一. C语言中的static关键字
0) C的static关键字的名字理解
static关键字,有人说他命名得不好?因为static翻译为中文是有安静的意思。但是,对于static关键字的使用来说,却一点都不安静,做的事情都很重要,比如修饰全局变量,和函数,使得该全局变量和函数只能在本文件中使用,不能直接的跨文件使用;修饰局部变量,使得该变量的声明周期得以延长,都是躁动的模样,强行改变别人的动向。
但我觉得它确实挺合适安静的名称的,修饰全局变量和函数时候,不能直接的跨文件使用了,就只能在本文件使用,这说明它使得全局变量和函数安安静静的呆在本文件中了,不能让别的文件访问了。
从不的角度想想这个关键字的名称其实也挺有意思的。
1) C的static关键字的两个作用
在C语言中,static关键字有两个作用:1.修饰变量,2. 修饰函数。
- 修饰变量又分为两种:第一种修饰全局变量,第二种修饰局部变量。
- 修饰全局变量,使得该全局变量只能在本文件中访问,不能直接的跨文件访问。(注意是直接)
- 修饰局部变量,使得该局部变量的声明周期得以延长,不至于出了作用域就销毁。
- 修饰函数,修饰函数使得该函数只能在本文件中访问,不能直接的跨文件访问。(注意直接)
下面仔细来讨论下如何理解两句话。
2) C的static修饰全局变量和修饰函数
satic关键字修饰全局变量和修饰函数的作用是一样的,所以放到一起讨论,都是使得他们不能够直接跨文件访问,限制他们只能在本文件访问。
首先,我们创建两个.c文件,一个为main.c
,一个为test.c
;文件名是什么不重要,只要他们不同名,且后缀为.c文件即可。
现在我要做一些事情,在 test.c 文件书写,下面的语句:
//test.c文件的内容
int i = 10; //全局遍历 i
在 main.c文件中书写下面的语句:
//main.c文件的内容
我要问一个问题,请问,当我编译运行时候,是否可以成功运行上面的程序?
答:是不可以的。因为 变量 i是未被定义的。看编译器的报错信息。
我要继续问,我明明在test.c文件中定义了int i = 10;为什么在 main.c文件中不能够访问?如何才能使得main.c文件能够访问到 test.c文件中的 i 呢?
答:首先,在main.c文件不能够访问test.c文件的原因很简单,因为编译是单独编译每一个.c文件的,很明显编译器不认识i;所以会报错。要想使得编译器认识 i, 那么就得在main.c文件中声明 i,即
extern int i
;这样 编译器就认识了 i,于此同时,在链接阶段,就会把test.c文件中的 i链接过来,那么就可在 main.c文件中访问到test.c的文件中的全局变量 i了。
即,我在main.c文件添加 extren int i语句,添加后:
# include<stdio.h>
extern int i; //声明全局变量
int main()
{
printf("%d\n", i); //声明后可以成功访问,该test.c的全局变量i = 20;
return 0;
}
上诉编译就不报错了,这就可以成功访问的其他文件的test.c
的变量 i
,即在main.c
文件访问了test.c
文件的 变量i
.
那假如我有一种需求,那就是我不希望我的全局变量 i
能够被其他文件访问,即我就想我的全局变量 i
就只能在本文件中访问 ,可以做到那?当然可以,那就是我们static关键字的作用,修饰全局变量,使得该全局变量不能够被跨文件访问,即test.c文件的全局变量 i,不能够在 main.c文件中使用。
所以,我们在 test.c添加关键字static 修饰 int i 20;添加后的test.c文件为:
//添加了 static 关键字的 test.c文件
static int i;
我们尝试,在 main.c文件中访问test.c文件中的全局变量 i,看看会发生什么事?
也是,无法解析的外部命令报错,这说明在链接时候,没有在main函数找到 变量 i,是因为我用static修饰了 test.c文件中的变量 i,使得该变量i,只能在test.c文件使用。
其实static,修饰函数也是和修饰全局变量一个道理,我们在 test.c文件中添加一个static 修饰的函数,去掉刚刚的 static int i;
//static int i;
static void show() //在test.c中用static修饰的函数
{
printf("!!!!!!!!!!!");
}
我们在 main.c中也声明该函数,于此同时调用该函数,看看是否成功?
很明显,也是调用失败的,说明static修饰函数也可以使得该函数,不能直接够跨文件访问。
但是,有一点很重要虽然,我们知道,static修饰的全局变量和全局函数不能够被跨文件访问,但是,他们却可以间接的跨文件访问.朋友门可以自行验证。
比如我提供一个非 static修饰的函数,在里面调用了 static修饰的函数,那么,我们就可以跨文件访问没有被 static 修饰的函数,从而间接访问 static 修饰的函数。
这也很好的体现了一种封装性,由于 static修饰函数,直能服务于本文件的,那么该函数接口就不会暴露出去,说明该函数相对有隐私一点,类似C++中,类的private。
3) C的static修饰局部变量
相信大家都了解static这个功能,修饰局部变量能够使得该局部变量不用出了作用域就直接直接销毁,而是能够继续存活下来,存活到整个程序从头到尾运行结束后,它才会销毁,这也说明static修饰的局部变量,当中值发生了改变,出了作用域也会保留该值。
static修饰局部变量,该局部变量是在编译期间就确定好值的了,所以必须初始化,不用等到运行时候才分配内存。
朋友们可以自行在 main.c数中定义一个局部变量,用static修饰,并且在static修饰的局部变量打一个断点,运行时候,你会发现,这个断点被跳过了,直接说明该static修饰的语句,在程序运行时候,不执行,但你监视它的值,确实存在,也就说明,该static修饰的局部变量,编译时候就确定初始值,运行时候就不执行该static修饰的局部变量啦。
4) C的static关键字总结
C 的 static 关键字修饰全局变量和修饰函数,使得该函数不能够直接的跨文件访问,但是能够间接的访问;
C 的 static 关键字修饰局部变量,该局部变量必须初始化,编译期间确定初始值,并且该局部变量的声明周期得以延长,不至于出作用域就销毁,知道程序运行结束才销毁。
二. C++中的static关键字
在C++上,由于多了类,所以C++中的关键字,不仅仅是用来修饰全局变量和函数,局部变量的,还会在此基础上(C++中static 修饰全局函数和修饰函数,局部变量依旧是一样的功能),增加了对类中 成员变量,成员函数的修饰。
其实我之前有篇文章就是关于C++中static修饰类的成员说明:static修饰类中的成员,在这里我就不多赘述啦。
三.static在C和C++的区别和相同
相同:
- 他们无论在C还是C++都修饰全局变量和局部变量和函数都是一样的。
区别:
3. 在C++中多了类,在类中,static修饰的成员变量只能类内声明,类外初始化,不向C中修饰变量,直接需要初始化,
4. 在C++中static修饰成员函数,该成员函数,只能使用static修饰的变量,不像C语言中的static修饰函数,可以在static函数里面使用任何类型的变量。
5. 在C++中,static修饰的成员(变量和函数),都是只保留一份,并且跟随对象的,就算你创建几百个对象,这里的static成员也就是一份数据。无论你在哪个对象改变了static成员的数据,在其他对象的static成员数据也会改变,因为就一份static的数据。
四. 总结
static关键字有超级多妙用的方法,这里只是简单的说明一下,如何正确的使用static关键字,帮助大家阅读static关键字的作用,等以后见多别人代码,用到static关键字,你就知道如何使用了。