第九讲 变量类别与编译预处理
 
  引 言

  一、教学目的
  本讲主要介绍了全局变量和局部变量以及自动变量、静态变量和寄存器变量的特点和关系,介绍了编译预处理命令中的宏定义和文件包含,要求大家掌握局部变量和全局变量的特点和使用方法,了解自动变量和静态变量的区别,掌握不带参数的宏和带参数的宏的使用,熟练运用“文件包含”功能。

  二、知识要点
  1.全局变量和局部变量
  (1)局部变量的特点
  (2)全局变量的特点
  (3)全局变量的应用
  2.自动变量、静态变量和寄存器变量
  (1)自动变量的存储形式
  (2)静态变量的存储形式和使用注意事项
  (3)寄存器变量的存储形式
  3.宏定义
  (1)不带参数的宏定义
  (2)带参数的宏定义
  4.文件包含
  文件包含的作用和使用方法

  三、边用边学

  §9.1 全局变量和局部变量

  C语言根据变量作用域的不同,将变量分为局部变量和全局变量。

  一、局部变量
  在函数内部定义的变量称为局部变量,它只在定义它的函数内部有效,即局部变量只有在定义它的函数内部使用,其它函数不能使用它。

  二、全局变量
  在所有函数外部定义的变量称为全局变量。全局变量的作用范围是从定义变量的位置开始到源程序结束,即全局变量可以被在其定义位置之后的其它函数所共享。
  全局变量主要用于函数之间数据的传递。具体应用在两方面:一是函数可以将结果保存在全局变量中,这样函数得到多个执行结果,而不局限于一个返回值;二是由于函数可以直接使用全局变量的数据,从而减少了函数调用时的参数。

  §9.2 自动变量、静态变量和寄存器变量

  C语言的变量根据分配的存储空间的不同,可以分为寄存器变量、静态变量和自动变量。

  一、自动变量
  自动变量的存储空间为内存中的动态数据区,该区域中的数据随程序需要动态地生成或释放。在函数体内或者复合语句内定义的局部变量都属于自动变量。
  自动变量的类型修饰符auto放在变量的类型说明之前。但是auto一般是不写的。局部变量只要不专门说明是static存储类型,都确定为自动变量,采用动态存储方式。
  自动变量的特点是当程序执行到自动变量的作用域时,才为自动变量分配存储空间,并且定义自动变量的函数执行结束后,程序将释放该自动变量的存储空间,留给其它自动变量使用。

  二、静态变量
  静态变量的存储空间为内存中的静态数据区,该区域中的数据在整个程序的运行期间一直占用这些存储空间,直到整个程序运行结束。
  所有的全局变量都是静态变量,而局部变量只有定义时加上类型修饰符static,才为局部静态变量。
  静态变量的特点是在程序的整个执行过程中始终存在,但是在它作用域之外不能使用。即静态变量的生存期就是整个程序的运行期。
  在选择使用静态局部变量还是自动变量,可以从以下两点考虑:一是如果需要在两次函数调用之间保持上一次函数调用结果,可以使用局部静态变量;二是如果在每次调用函数时都必须对局部变量初始化,选择自动变量。但是实际上局部静态变量占用内存时间较长,并且可读性差,因此,除非必要,尽量避免使用局部静态变量。

  三、寄存器变量
  为了提高运算速度,C语言允许将一些频繁使用的局部变量定义为寄存器变量,这样程序尽可能地为它分配寄存器存放,而不用内存。
  寄存器变量只要在定义时加上类型修饰符register即可。

  四、用extern、static声明的全局变量
  如果组成这一个程序的几个文件需要用到同一个全局变量,只要在其它引用该全局变量的源程序文件中说明该全局变量为extern即可。
  反之,如果希望一个源程序文件中的全局变量仅限于该文件使用,只要在该全局变量定义时的类型说明前加一个static。

  §9.3 宏定义

  C语言提供的预处理命令主要有:宏定义、文件包含和条件编译。其中宏定义分为带参数的宏定义和不带参数的宏定义。

  一、不带参数的宏定义
  不带参数的宏定义的一般形式为
    #define 标识符 字符串
  它的作用是在编译预处理时,将源程序中所有标识符替换成字符串。
  无参数的宏定义使用时,要注意以下几个问题:
  (1)宏名一般用大写字母,以便与变量名的区别。
  (2)在编译预处理时宏名与字符串进行替换时,不作语法检查。
  (3)宏名的有效范围是从定义位置到文件结束。如果需要终止宏定义的作用域,可以用#undef命令。
  (4)宏定义时可以引用已经定义的宏名。
  (5)对程序中用双引号扩起来的字符串内的字符,不进行宏的替换操作。

  二、带参数的宏定义
  带参数的宏定义的一般形式为
    #define 标识符(参数表)字符串
  它的作用是在编译预处理时,将源程序中所有标识符替换成字符串,并且将字符串中的参数用实际使用的参数替换。
  带参数的宏定义使用时,要注意以下几个问题:
  (1)在宏定义时,宏名和参数之间不能有空格。
  (2)一般在定义宏时,字符串中的形式参数外面加一个小括号。

  §9.4 文件包含

  “文件包含”用于一个源程序文件包含另外一个源程序文件的全部内容。“提供的文件包含预处理命令的一般形式:
    #include <文件名>
  或者
    #include “文件名”
  “文件包含”的使用时要注意:
  (1)一个#include命令只能指定一个被包含的文件。
  (2)“文件包含”可以嵌套。
  作业及上机练习
  1.使用全局变量,编写程序实现通过调用一个函数double calculate(double x,double y),可以得到两个数的和、差、积、商。
  2.应用局部静态变量实现输入n,输出1+2+3+… …+n的结果。
  3.输出Fibonacci数列的前20项的值。应用局部静态变量的方法。
  4.定义带参数的宏MAX(a,b)、MIN(a,b)、ABS(a)分别求两个数的最大值、最小值和一个数的绝对值。
  5.定义宏名Leap_Year(year)和Isupper(a),判断year是否是闰年以及a是否是大写字母。
  6.已知三角形的边长a、b、c,求三角形的面积
  
  其中s=(a+b+c)/2。要求定义两个带参数的宏用来表示s和area。
  7.使用符号常量N代表学生人数,进一步完善“学生成绩管理系统”。