1. #define
首先请看以下程序:
#include < stdio.h>
#define PERCENT 0.1
int main(void)
{
int income = 4000;
printf("%.2f", PERCENT * income);
return 0;
}
这个程序输出 400.00 。这是因为 #define PERCENT 0.1 定义了一个符号名 (symbolic name ),这个符号名就是 PERCENT,它的值为 0.1。当程序被编译时,程序中所有在 #define PERCENT 0.1 后面 的 PERCENT 都会被替换成 0.1。注意,必须完全匹配 才会被替换,PERCENTS(如果有的话)绝对不会被替换成 0.1S !字符串常量也不会被替换。"PERCENT"(如果有的话)绝对不会被替换成 "0.1" !这种替换就是所谓的编译时替换 。从源代码到可执行文件要经历三个阶段:预处理、编译,链接 。编译时替换是在预处理阶段,由预处理器 (Preprocessor )完成的。上述程序预处理后变成:
// 这里被替换成头文件 stdio.h 中的内容
int main(void)
{
int income = 4000;
printf("%.2f", 0.1 * income); // PERCENT 被替换成 0.1
return 0;
}
前面的教程中我们说过预处理指令 #include 是怎么工作的(点击查看 )。这里的 #define 也是一个预处理指令,使用其定义符号名的方法为:
#define 符号名 替换列表
符号名必须符合标识符命名规则(点击查看 )。替换列表 可以是任意字符序列,如数字、字符、字符串字面量、表达式等等。例如:
#define MSG "I'm Antigloss!" /* 后面的所有 MSG 都会被替换为 "I'm Antigloss!" */
#define SUM 50 + 99 /* 后面的所有 SUM 都会被替换为 50 + 99 */
#define BEEP '\a' /* 后面的所有 BEEP 都会被替换为 '\a' */
注意,预处理指令 #define 的最后面没有分号(;),千万不要画蛇添足!
如果替换列表 由值为常量的表达式 构成,习惯上我们把其对应的符号名称为符号常量 (symbolic constant )。习惯上我们用大写字母 来命名符号常量,而用小写字母 来命名变量。
切记,符号名之后,换行之前的一切内容都属于替换列表(当然,注释除外),后面所有出现符号名的地方都会被替换成与该符号名相应的替换列表中的内容。千万别犯这种低级错误:
#define STEP = 20
如果你这样做了,后面的 STEP 都会被替换成 = 20 。这样的话,类似
total_min = min * STEP;
的语句就会被替换成
total_min = min * = 20 ; // 错误
2. const 修饰符
我们也可以使用 const 修饰符来定义常量 :
const int INCOME = 4000; // INCOME 是常量,它的值是 4000
以上语句声明了一个 int 型常量。我们只能读取 INCOME 的值,而不能修改 它的值。通常,我们把这种常量也称为符号常量。
3. 使用符号常量的好处
符号常量可以提醒我们它的作用。例如:
tax = income * PERCENT;
tax = income * 0.1;
第二个语句中的 0.1 让人摸不着头脑,不知道它是干什么的;而第一个语句,看到 PERCENT 我们就可以知道这是一个百分比。
如果程序中多个地方使用了同一个常量(如 0.1),当我们需要修改这个常量时,必须修改用到该常量的所有地方。工作量大暂且不提,更可怕的是我们可能会漏改、错改,或者误改了某些不该改的常量。而使用符号常量就不同了。我们只要把符号常量的值改掉就行了