一、宏定义
1、不带参数的宏定义
用一个指定的标识符(即名字)来代表一个字符串,它的一般形式为:
#define 标识符 字符串
这就是已经介绍过的定义符号常量。
说明:
(1)宏名一般习惯用大写字母表示,以便与变量名相区别,但这并非规定,也可用小写字母。
(2)使用宏名代替一个字符串,可以减少程序中重复书写某些字符串的工作量。
(3)宏定义是用宏名代替一个字符串,也就是作简单的置换,不作正确性检查。
(4)宏定义不是C语句,不必在行末加分号。如果加了分号则会连分号一起进行置换。
(5)#define命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到本源文件结束。
(6)可以用#undef命令终止宏定义的作用域。
(7)在进行宏定义时,可以引用已定义的宏名,可以层层置换。
(8)对程序中用双撇号括起来的字符串内的字符,即使与宏名相同,也不进行置换。
(9)宏定义是专门用于预处理命令的一个专用名词,它与定义变量的含义不同,只作 字符替换,不分配内存空间。
2、带参数的宏定义
带参数的宏定义不是进行简单的字符串替换,还要进行参数替换。其定义的一般形 式为:
#define 宏名(参数表) 字符串
字符串中包含在括号中所指定的参数。
说明:
(1)对带参数的宏的展开只是将语句中的宏名后面括号内的实参字符串代替 #define命令行中的形参。
(2)在宏定义时,在宏名与带参数的括号之间不应加空格;否则将空格以后的字符都 作为替代字符串的一部分。
带参数的宏定义与函数的不同处:
(1)函数调用时,先求出实参表达式的值,然后代入形参。而使用带参数的宏只是进 行简单的字符替换。
(2)函数调用是在程序运行时处理的,为形参分配临时的内存单元。而宏展开则是在 编译前进行的,在展开时并不分配内存单元,不进行值的传递处理,也没有“返回值”的概念。
(3)对函数中的实参和形参都要定义类型,二者的类型要求一致,如不一致,应进行类型转换。而宏不存在类型问题,宏名无类型,它的参数也无类型,只是一个符号代表,展开时代入指定的字符串即可。宏定义时,字符串可以是任何类型的数据。
(4)调用函数只可得到一个返回值,而用宏可以设法得到几个结果。
(5)使用宏次数多时,宏展开后源程序变长,因为每展开一次都使程序增长,而函数调用不会使源程序变长。
(6)宏替换不占运行时间,只占编译时间。而函数调用则占运行时间(分配单元、保 留现场、值传递、返回)。
二、“文件包含”处理
所谓“文件包含”处理是指一个源文件可以将另外一个源文件的全部内容包含进来, 即将另外的文件包含到本文件之中。C语言提供了#include命令用来实现“文件包含” 的操作。其一般形式为:
#include"文件名"
或
#include<文件名>
说明:
(1)一个#include命令只能指定一个被包含文件,如果要包含n个文件,要用n个 #include命令。
(2)如果文件1包含文件2,而在文件2中要用到文件3的内容,则可在文件1中用 两个include命令分别包含文件2和文件3,而且文件3应出现在文件2之前。
(3)在一个被包含文件中又可以包含另一个被包含文件,即文件包含是可以嵌套的。
(4)在#include命令中,文件名可以用双撇号或尖括号括起来。
(5)被包含文件(file2.h)与其所在的文件(即用#include命令的源文件filel.c),在 预编译后已成为同一个文件(而不是两个文件)。
三、条件编译
程序中一部分内容只在满足一定条件时才进行编译,也就是对这一部分内容指定编译的条件,这就是“条件编译”。
条件编译命令有以下几种形式:
(1)#ifdef标识符
程序段1
#else
序段2
#end
或 #ifdef标识符
程序段1
endif
(2)#ifndef标识符
程序段1
#else
程序段2
#endif
(3)#if表达式
程序段1
#else
程序段2
#endif