在文章嵌入式Linux开发《C语言专题(十:彻底搞懂“关键字”const)》中对C语言中const关键字的用法做了详细介绍。这篇文章将详细介绍C语言中的另外一个很重要的关键字static,C++中对static关键字做了相应扩展,这里不讲,感兴趣的小伙伴可以去看看。在实际做项目和笔试、面试中有很大作用。笔者就曾在笔试中遇到要求写出关键字static的作用这类题目。
看完这篇文章你将不仅可以看懂关于static的代码,而且还会使用static修饰变量(局部变量和全局变量)、函数的应用场景。按照以前的惯例,用代码来验证static的功能。
(1)static修饰变量
1)修饰局部变量
修饰局部变量又称之为“静态局部变量”。一般都在函数体内,作用范围为该函数体,该变量的内存只能被分配一次,并且具有“记忆功能”即下次调用这个函数时维持上次的值。
运行结果:
分析结果:从结果中我们可以看到fun2函数的运行结果发生改变而fun1的不改变。原因是static关键字修饰的局部变量存储在静态区。改变了变量的生命周期,使得变量的生命周期变为整个程序(只要系统运行不停止会继续保持上一次的值)。所以,如果在项目开发时需要一个函数运行完继续保留上一次的值,那么就可以将这个变量定义为静态局部变量。
2)修饰全局变量
修饰局部变量又称之为“静态全局变量”,使用方式如下代码所示:
运行结果:
分析结果:因为a++操作所以a的值变为11,说明在main函数和fun1函数中都可以访问静态全局变量的值。但是在别的文件中不能访问这个变量。作用域为整个文件(确切的说是从定义开始到文件结束)。这样做的原因是防止在做项目时不同的研发人员在做同一个项目中时定义变量名冲突,导致出错。如果在别的文件中访问static全局变量会产生哪些结果?下面就用代码演示:有2个.c文件:main.c和calculte.c main.c中要调用calculate.c中的static全局变量。
1)main.c代码
2)calculate.c代码
运行结果:
分析结果:编译出错,提示原因为没有定义a,因为a是一个不在main.c中定义的静态全局变量。如果将calculate.c代码中的static int a = 10;改为 int a = 10,那么编译通过并且运行结果也正确。如下图所示:
(2)static修饰函数
修饰函数又称之为“静态函数”。写法就是在函数的定义和声明前加上static,如下所示:
运行结果:
分析结果:
修饰函数其实是将所要修饰的这个函数的作用域限定在这个文件作用域中,也就是在这个文件中可以使用这个函数,在别的文件中是不能用这个函数中。这样做好处一方面使代码符合软件设计的规则:高内聚、低耦合,可以对这些函数做一些封装;另一方面不同的人编写不同的函数时,加上static后不用担心函数名重名。因为在大型公司做开发时,往往是团队合作,每个人只完成一部分功能,难免会定义相同的函数名。如果确实在别的文件中要用这个函数,那么用extern关键字来代替static关键字。下面就用代码演示在别的文件中访问static函数会产生哪些后果?
有2个.c文件:main.c和calculte.c main.c中要调用calculate.c中的static函数
1)main.c代码
运行结果:
分析结果:编译就出错,提示为没有定义cal函数,因为cal函数不是在main.c文件中定义的,而在别的文件中定义的静态函数。如果将calculate.c代码中static void cal(void)改为void cal(void)皆可以编译并运行成功。
总结
1)static修饰的变量都是存储在静态存储区,与堆和栈相区别,默认初始化值为0.
2)static修饰局部变量时,改变的是变量的生命周期,并且在每一次运行完这个函数后,这个变量的值会一直保存,直到程序终止。
3)static修饰全局变量,改变的是变量的作用域也即这个变量只能从这个文件的定义开始使用到这个文件的结束。
4)static修饰函数,与修饰全局变量类似,都是改变变量的作用域
因此,在实际的研发中根据实际的应用场景来选择static的不同用法。