前面章节中代码里硬写入像 300、20 这类魔法数(magic numbers)是糟糕的编程习惯:
后续阅读代码的人很难看懂这些数字的含义;
而且当需要统一修改数值时,维护十分麻烦。
处理魔法数的方案之一,就是给数字赋予有意义的名字。利用 #define 指令可以定义符号名 / 符号常量,语法格式:
#define name 替换文本Code language: C++ (cpp)
定义之后,源代码中所有独立出现的 name(字符串引号内、或是作为其他标识符一部分的除外),都会被替换文本原样替换。
符号名命名规则和变量一致:由字母、数字组成,且首字符必须是字母。
替换文本可以是任意字符序列,不局限于数字。
#include <stdio.h>
#define LOWER 0 // 表格下限
#define UPPER 300 // 表格上限
#define STEP 20 // 步长
/* 打印华氏-摄氏温度对照表 */
int main()
{
int fahr;
for (fahr = LOWER; fahr <= UPPER; fahr = fahr + STEP)
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}Code language: C++ (cpp)
执行结果和前面章节一样。
LOWER、UPPER、STEP 都是符号常量,不是变量,因此不需要变量声明。
惯例:符号常量名称全部大写,方便和小写命名的普通变量区分。(非硬性要求)
注意:#define 这一行末尾不要加分号!
汇总
- 预处理机制
#define属于预处理指令,编译正式代码之前,预处理器只会做简单文本替换,不存在类型检查。
例如fahr = LOWER在预处理后直接变成fahr = 0。 - 为什么不能带分号?
#define UPPER 300;Code language: C++ (cpp)
替换后代码:
for(fahr = 0; fahr <= 300<strong>;</strong>; fahr +=20)Code language: C++ (cpp)
多出分号,直接造成语法错误。
- 符号常量 vs 普通变量
#define:预处理文本替换,无内存分配,没有数据类型;const int(C标准常量):属于变量,占有内存,具备类型,运行期生效。
- 命名规范约定
常量全大写,下划线分隔:MAX_VALUE、BUFFER_SIZE;
普通变量小写/驼峰:fahr、tempValue。
例子
下面是另外一个倒过来的例子,结果也是一样。
#include <stdio.h>
#define LOWER 0
#define UPPER 300
#define STEP 20
int main(void)
{
int fahr;
for (fahr = UPPER; fahr >= LOWER; fahr -= STEP)
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr - 32));
return 0;
}Code language: C++ (cpp)
常量符号,就相当于编译器在正式编译之前做一次预处理,把所有的用到这个常量符号的地方都替换一遍,本质上最终编译的时候,和前面不适用常量符号的效果是一样的。
Previous: for循环