6.9 变量的作用域
某个变量的作用域(Scope)是指在代码中可以使用这个变量的区间或范围。
可以定义变量的位置有两个:其一是函数内,其二是函数外。
函数内定义的变量(包括形参)叫做局部变量。
函数体内的任何一个复合语句块(用“{}”括起来的由若干语句、定义或声明组成的一段程序模块)内都可以定义变量,这些变量也属于局部变量(12)。
局部变量只允许在自己所在的{}内被使用(形参是在所对应的函数体内),且必须是在被定义之后才能被使用。在这个范围之外,该局部变量是不可视的,也就是说是不可以被使用的。
下面的情形,属于两个同名变量的作用域发生重叠,这时编译器按照局部优先的原则处理。
这种情况中,内层{}用到的homonymy是指在内层定义的homonymy,这叫局部优先;在外层{}之内、内层{}之外用到的homonymy是外层定义的homonymy。
但这样的写法很滑稽,如果没有自虐倾向的话,估计没有人会这样写代码。尽管编译器可以帮助你区分开你使用的homonymy究竟是哪个homonymy,但你又何必自己折磨自己呢?
所以本书的忠告如下。
(1)尽量不要重名。
(2)如果重名发生在两个不同的作用区域,比如两个函数内都有一个变量叫做“i”,一般也无妨,因为它们的作用区间不同,就如同不同班级有两个同名的学生一样,只要他们不在同一个教室上课,不会带来什么麻烦和混乱。
(3)绝对避免重叠区域内的变量重名。
此外要说的一点是,C99允许在复合语句模块内的任何地方定义变量,但目前的多数编译器只支持在“{”之后立即定义或声明变量。例如下面的代码是支持C99的编译器所允许的,但在老式的编译器中则有语法错误。
函数外定义的变量叫做外部变量。外部变量的有效区间通常是从定义的位置开始,到源文件的结尾。但在本质上,源程序的各个函数定义内都可以使用外部变量,如果函数定义不在外部变量的作用区间,可以声明要求编译器帮忙查找并允许使用。具体的方法目前没必要了解。
外部变量与结构化程序设计思想是有矛盾的,因为外部变量加强了程序各个部分之间的联系,这样就增加了程序的复杂性(用流行的术语来说是提高了耦合度)。此外每个函数都可能错误地改变外部变量的值,也同样容易误用外部变量的值,这同样增加了程序出错的风险。对于专业人员来说,使用外部变量经常是两害相权的结果。对于初学者来说几乎没有任何使用外部变量的理由,那几乎是和使用goto语句类似的行为,而且绝对妨碍编程技术的提高。本书将在最后的章节适当介绍外部变量的使用,在此之前一律不使用外部变量。
此外顺便说一句,不但变量存在作用域,实际上所有的标识符都有自己的作用域。绝大多数标识符都不允许在定义之前被使用(13)。