C中的static和extern总结

我们知道,C语言中没有类的概念,代码都是以文件为单位组织的。对于非局部变量和函数,只能在唯一的一个C文件中定义一次,多文件同时定义就会导致编译器报重复定义的错误。而为了能在其他C代码文件中使用这些非局部变量和函数,就有了extern关键字。同时,为了文件的代码隔离,有些变量和函数不想被其他文件访问,就有了static关键字。
下面将围绕extern和static说明它们的作用。

1. extern 

1.1 extern修饰变量

为了使用在其他文件或其他地方定义的变量,需要使用extern来声明该变量。这里的"其他地方",比如在C++中,同一个源码文件,在定义该变量之前使用该变量;
当然在较老版本的C中,变量和函数必须先定义,才能使用。
举例来说,在a.c中定义的 int x; ,在b.c中 extern int a;,如果放于某个函数中,则可见性仅限该函数内;如果放于函数外,则对于定义该函数的文件内的所有函数都是可见的。
extern int a; 要求a的链接属性是外链接(external)的,如果a本身不符合外链接属性,即使extern修饰了该变量,也引用不成功。

1.2 extern修饰函数

与extern修饰变量类似,被修饰的函数也应是外链接的,才能引用。

1.3 extern和include

我们知道,引用其他模块的函数和变量,最常见的就是使用"#include"来修饰包含被引用函数的头文件,和这里extern作用类似。它们的区别主要是:
"include"声明头文件一次,就可以批量应用该头文件下的所有外链接的函数和变量;extern只能一次声明一个变量或函数;
extern目标明确,直接了当,代码结构清晰,也会加速编译过程,节省时间;
所以,如果需要多次引用同一个文件下的函数或变量,用"include"合适;否则使用extern合适。

1.4  extern "C"

在C++中调用C库,经常见到这样的代码,来声明要使用的函数是来自C中的。作用是告诉链接器,要使用C的函数命名规范来链接,而不是C++的。
因为C++编译后的函数命名和C的不同,如果使用C++的命名,链接器可能找不到编译后的函数。

2. static  

2.1 static局部变量

局部变量在函数中定义,通常是存放在栈中的,它的生命周期随着函数执行的结束而终止。而static修饰局部变量后,它存放于静态存储区.data段,.data段里面存放已初始化的全局变量。static局部变量的生命周期将随程序的结束而终止,而与定义它的函数的执行无关。但是由于它仍是一个局部变量,故它的作用域仍然是该函数内。同时,该变量只在初次定义时被初始化一次。如果没有显示的初始,那么系统会默认赋值。对于int型变量,系统会自动对其赋值为0,对于字符数组,会自动赋值为'\0'。

对于一次程序执行而言,static局部变量的每次操作,都是在上一次操作后的值的基础上进行操作的,对于多线程编程,这是需要注意的地方,需要做好代码块同步。

2.2 static全局变量

前面我们提到,可以通过extern修饰变量来引用在其他地方定义的全局变量,且该变量需为外链接的。而如果定义的全局变量不想被其他文件引用,即只在定义该全局变量的文件内有效的话,可以用static修饰全局变量达到这样的效果。这叫做静态全局变量。和其他的全局变量的存储相同,静态全局变量也是在.data段(已初始化)或者.bss段(未初始化)内存放的。

2.3 static函数

同static全局变量一样,static修饰函数也将函数的访问范围限定在了定义该函数的文件内部。外界的extern引用访问会报编译错误。好比面向对象语言中类中的private修饰符一样。

 

3. static和extern可以同时用吗?

其实上面我们已经说的很清楚了,static修饰的变量和函数的作用范围北限定于定义它们的文件内部。而extern修饰的变量和函数说明要引用在其他地方定义的变量和函数,显然这是两个矛盾的修饰符。更深层次的讲,extern要求引用的变量和函数是外链接的,他需要通过符号表名称进行链接,而static恰恰会移除符号表名称。即使在同一个文件里,static和extern同时修饰一个变量或函数来声明,之后再用static定义该函数, 依然是编译报错的。有兴趣的朋友可以去试试。

 

以上就是我对C中的static和extern总结,如有不足之处,欢迎指正。

版权声明:本文为博主原创文章,未经博主允许不得转载;来自https://blog.csdn.net/milanac007/article/details/83383846

 

 

 

 

 

你可能感兴趣的:(Android)