14.2.1 宏
#define包括一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)。
#define SQUARE(x) x * x
则程序中的SQUARE(5)会被替换成:5 * 5
警告:
例1:
a = 5;
printf("%d\n", SQUARE(a + 1));
会被替换成5 + 1 * 5 + 1,打印结果是11,不是36。
例2:
#define SQUARE(x) (x) + (x)
a = 5;
printf("%d\n", 10 * SQUARE(a));
会变成10 * 5 + 5,打印结果是55,不是100。
正确定义为:#define SQUARE(x) ((x) + (x))
因此,所有用于求值的宏定义都应该加上括号,避免使用宏时,
由于参数中的操作符或邻近操作符之间不可预料的相互作用。
14.2.3 宏与函数
#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
为什么不用函数来完成这个任务?
1. 用于调用和从函数返回的代码可能比实际执行这个小型计算的代码更大。
2. 函数的参数必须声明为一种特定的类型,而宏与类型无关。
3. 有些任务根本无法用函数实现:
#define MALLOC(n, type) ( (type *)malloc( (n) * sizeof(type) ) )
pi = MALLOC(25, int);
pi = ( (int *)malloc( (25) * sizeof(int) ) );
14.2.7 命令行定义
C编译器允许在命令行中定义符号。当根据同一个源文件编译一个程序的不同版本时很有用。
int array[ARRAY_SIZE];
cc -DARRAY_SIZE=100 prog.c
14.3 条件编译
避免为每个版本编写一组不同的源文件。因为各组源文件的绝大多数代码都是一样的。
void fun1(arguments)
{
#if FEATURE_ENABLED_FULLY
feature_function(arguments);
#elif FEATURE_ENABLED_PARTIALLY
feature_partial_function(arguments);
#else
printf("Send $39.95 to allow ten weeks for delivery.\n");
#endif
}
14.4 文件包含
多重包含常出现在大型程序中。要解决这个问题,所有的头文件要这样写:
#ifndef _HEADERNAME_H
#define _HEADERNAME_H 1
/*
** All the stuff that you want in the header file
*/
#endif
必须记住预处理器仍将读入整个头文件,即使这个文件的所有内容将被忽略。