在C语言中创建一个变量,意味着在内存中为其开辟一个空间,也就是为这个变量分配一个地盘。仅仅开辟完地盘就可以了吗?毕竟地盘是有边界的!这篇谈下变量作用域。
创建一个变量的时候,我们可以通过C语言给出的几个关键字指定变量不同的生存期,如何给变量分配存储空间,在哪分配空间以及编译器怎样处理这些变量。 在谈论这些问题前,先看两个概念“外部变量”和“内部变量”。由于C语言规定在函数内部不可以定义另外一个函数。站在C语言函数这个角度看的话,你会发现C语言的世界就两个:函数内部的世界(在内部世界中定义的变量就是内部变量)和函数外部的世界(在函数外部世界定义的变量就是外部变量)。从这看出函数本身其实也是“外部的”,故函数可以被其它函数调用。还要区分一个概念“文件外部变量”,这里我这么叫“文件”外部变量,是为了区分“外部变量”这个概念的。 在缺省情况下“外部变量”具有的性质是:所有通过名字对外部变量及函数的引用都是引用的同一对象,不管这个对象是否来自同一个文件(毕竟C语言的函数可以以单独文件进行独立编译)。如果对外部变量的引用来自同一个文件就叫“内部链接”,如果这个外部变量来自其它文件,就叫“外部链接”。关于这两种链接会单独进行说明,这里暂且不说,先记住就可以了。 接下来总结作用域下变量表现的四种不同方式: 全局变量、局部变量、静态变量和“文件外部变量” 。 首先看下全局变量: 由上面“外部变量”的概念应该容易得到这个全局变量的含义。全局变量就是在所有函数体的外部定义的,程序中的所有部分(甚至其它文件中的代码)都可以使用的变量。全局变量的作用域是整个程序运行期间。以下采用CodeBlock建立一个Console application作为案例讲解,项目如图1所示:
图1 项目结构图
main.cpp代码如图2所示:图2 main代码示意
fun.cpp代码如图3所示:
图3 fun.cpp代码
在main中定义一个全局变量global,这个之所以称为全局变量就是因为该变量定义在了函数外部,仅此而已!一旦定义了这个全局变量,该变量既可以在本文件中使用,如图2所示在main函数中使用;也可以在其它文件中使用,如图3所示,在fun.cpp文件中使用,但注意:在fun.cpp使用的时候得使用extern关键字声明该变量。一旦使用extern,那么编译器就知道该变量仅仅是说明下而已,不需要在这里分配空间,而且编译器还将知道该变量来自该文件的外部。
这里思考个问题,在函数内部可以使用extern修饰一个变量名吗?答案是“当然不可以”。毕竟进入到函数内部可是真刀真枪的去“落实事情”,要“落实事情”当然就需要有确定的“地盘”,想想extern,为不分配地盘而存在。
这里再思考个问题,想想这个main函数运行完后,前后两次输出结果是多少呢?一个10,一个20。为啥呢?“所有通过名字对外部变量及函数的引用都是引用的同一对象”,如此而已!
接下来再看下局部变量:
局部变量出现在一个作用域内,它们是局限于一个函数或者一对花括号的。局部变量有时称为自动变量(auto),仅仅是因为出了属于它的作用域,自己主动就销毁了。关键字auto可以显示说明该变量这个特性,而局部变量默认就是auto,所以没必要将其声明为auto。
局部变量中还可以出现 register关键字,这个关键字告诉编译器“尽可能快地访问这个变量”,这个关键字仅仅是暗示“编译器”,至于快不快那就看具体情况了,因此此关键字貌似用到的很少吧。毕竟编译器的优化器本身可以决定局部变量以何种方式进行最佳访问!
静态变量:
关键字static修饰的变量就是静态变量。静态变量可以在函数中使用,也可以在函数外使用,这两种决定了变量的不同性质。
函数中定义的局部变量在函数作用域结束时会消失,再次调用该函数时,会再次创建该变量的的存储空间,其值也会被重新初始化。但如果该变量前面加上static关键字,神奇的事情就发生了,该变量就算该函数结束了也不会释放空间,“会在程序运行期间一直存在”。只是函数内部定义的变量局限在了该函数内部。
如果static修饰的变量在函数外部或者修饰在函数前面呢?“局限在本文件内”了!哦,原来static具有双重作用呢。函数内作用域和文件作用域,这里好好想想!
如图4所示:
图4 定义static内部变量
这样在main函数中多次调用add函数后,会发现这个count的值会一直增加。有的同学可能会说,直接定义个全局变量不就得了,为啥还用这种方式呢?“让错误局部化的同时,可以使用类似全局变量的效果”!
最后看下“文件外部变量”:
前面已经对extern进行了说明,它告诉编译器存在着一个变量和函数,即使编译器在当前编译器中没有找到,但依然可以正确编译,因为编译器知道该变量可能在“外部文件”中。正是因为这个关键字的存在,决定变量的两种链接方式(内部链接和外部链接)。对于这两种方式的链接方式,会单独写篇文章进行说明。
END