今天对C语言中static和extern关键字的作用认识又深刻了
用了这么久的C语言,之前对于static关键字的用法总是一知半解,今天终于搞清楚了,写个文章简单记录一下。
用static修饰的变量,不管是全局变量还是局部变量,其存储位置都是静态存储区,全局变量作用域是当前文件,局部变量是其定义的函数块内部。
需要注意的是,用static修饰后的局部变量其生命周期是在整个程序运行期间,而不再是在函数执行完销毁。
对于全局变量和函数来说,有没有static修饰影响着其链接属性,如果都不加static修饰,那么其链接属性就是外部链接,什么意思呢,举个例子。假设a.c和b.c是一起编译的两个文件,它们在编译完成后,其各自的目标文件a.o和b.o就会被链接在一起形成一个可执行文件。
//文件a.c
int global = 10;
int fun()
{...
}
对于上面的全局变量和函数,它们在源文件a.c中被定义,但是如果我想在b.c文件中调用这两个值也是可以的,具体操作如下。
//文件b.c
extern int global;
extern int fun();
global = 20;
通过加extern关键字修饰就可以在本文件中使用另一个源文件中定义的全局变量或者函数了,而且对于全局变量,引入后还可以对其进行修改,修改后的值在后面的代码中生效。对于通过extern引入的函数,在本文件中就不能再定义同名函数了。
如果像下面这样通过static函数修饰全局变量和函数,那么即使在另一个文件中通过extern引入,也无法使用,因为static将其限制在本文件使用。
//文件a.c
static int global;
static int fun()
{...
}
也就是说,这个时候你就可以在另一个文件中定义和上面同名的全局变量和函数名称了,前提是在两个文件内部的相关变量前都得加上static修饰。
//文件b.c
static int global;
static int fun()
{...
}
现在仔细想一想,其实extern的作用有点类似于头文件,在源文件中引入头文件之后,头文件中的所有内容都会在编译预处理阶段展开,里面的全局变量和函数都可以被使用,但是如果头文件中只是声明了函数,那么函数的实现还需要另外一个源文件。extern就是轻量级的引入,而且也少了中间的头文件过渡,想要什么函数或变量可以通过extern引入到本文件中使用。
对于简单的文件关系和较少的函数调用,extern或许能够发挥比较好的作用。