先学习下关键字“static”用法
1: “static”第一个作用,也是它最重要的重要 隐藏
当同时编译多个文件时,所有未加"static"前缀的变量和函数具有全局可见性
例:同时编译 a.c和 main.c
//a.c
char a='A';
void msg()
{
printf("hello\n");
}
//main.c
int main()
{
extern a;
printf("%c",a);
(void)msg();
return 0;
}
输出结果是:A Hello
为什么在a.c中定义的全局变量a和函数msg能在main.c中使用?前面说过,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。此例中,a是全局变量,msg是函数,并且都没有加static前缀,因此对于另外的源文件main.c是可见的。如果加了static,就会对其它源文件隐藏。例如在a和msg的定义前加上static,main.c就看不到它们了。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏.
2:static第二个作用是保持变量内容的持久
存储在静态存储区的变量会在程序刚开始运行的时候完成初始化,也是唯一的一次初始化,共有两种变量存储在静态存储区:全局变量和用static声明的变量,只不过和全局变量比起来,static可以控制变量的可见范围,说到底static还是用来隐藏的。
PS:如果作为static局部变量在函数内定义,它的生存期为整个程序源,但是其作用域仍与自动变量相同,只能在定义该变量的函数内部使用,退出该函数,尽管变量还存在,但不能使用它。
#include"stdio.h"
int fun()
{
static int count =10; //在第一次进入该函数时,变量count被初始化为10,以后每次进入该函数都不会被初始化,
//仅进行自减1的操作,
return count--;
}
int count 1;
int main(void)
{
printf("global\t\tlocal static\n");
for(; count <= 10; ++count)
printf("%d\t\t%d\n", count, fun());
return 0;
}
global local static 1 10 2 9 3 8 4 7 5 6 6 5 7 4 8 3 9 2 10 1 |
---基于以上两点可以得出一个结论:把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。因此static 这个说明符在不同的地方所起的作用是不同的。
3.static的第三个作用是默认初始化为0(static变量)
4.static的第四个作用:C++中的类成员声明static(有些地方与以上作用重叠)
再学习下关键字“extern”用法
extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器在遇到此变量时需到其它模块中寻找定义。
如果函数的声明中带有extern,说明这个函数定义在其他文件中,这样的好处是可以取代include”*.h”,在一些复杂的项目中这样使用比较方便
再学习下关键字“volatile用法
volatile int i = 10;
int k = i;
这段代码如果没有加上volatile,它的执行过程是 i = 10, 10 ->reg寄存器,k = reg值,就是说,k=i实际上是从寄存器里读出来的。这样快捷高效,当然并不是每次都这样,因为寄存器有限。如果在10->reg寄存器的时候,i存储的内存变化了,也就是别的线程修改了i的值,k=i仍然会按照i=10来执行
加上volatile后,执行过程是 i = 10, k = *(int *)(&i); 它会从i的内存地址上去读,当然值会非常准确,但是效率会比从寄存器中读要慢很多。