第七章、宏与枚举
7.1 宏
规则7-1-1 用宏定义表达式时,要使用完备的括号。
说明:M为宏只是简单的代码替换,不会像函数一样先将参数计算后,再传递。
示例:如下定义的宏都存在一定的风险。
反例:
//若有除法运算,c/a*b计算错误
#define RECTANGLE_AREA(a, b) a*b
//a+1*b+1计算错误
#define RECTANGLE_AREA(a, b) (a*b)
//若有除法运算,c/(a)*(b)计算错误
#define RECTANGLE_AREA(a, b) (a)*(b)
正例:
#define RECTANGLE AREA(a, b) ((a)*(b))
规则7-1-2 使用宏定义多行语句时, 必须使用 { } 把这些语句括起来。
说明:在宏定义中,对多行语句使用大括号,可以避免可能发生的错误。
规则7-1-3 使用宏时,不允许参数发生变化。
例如:
有以下宏定义:
#define SQUARE( a ) ((a) * (a))
反例:
int a = 5;
int b;
b = SQUARE( a++ ); // 宏参数a变化,结果:a = 7,即执行了2次加1
正例:
int a = 5;
int b;
b = SQUARE( a );
a++; // 结果:a = 6,即只执行了 1 次加 1
规则7-1-4 不允许直接使用魔鬼数字**
什么是代码中的魔鬼数字,如何解决?
建议7-1-1 除非必要,应尽可能使用函数代替宏。
宏对比函数的缺点:
(1)宏缺乏类型检查,不如函数调用严格;
宏展开可能会产生副作用。
(2)以宏形式写的代码难以调试/打断点,不利于定位问题。
(3)宏如果调用很多,会造成代码空间的浪费,不如函数空间效率高。
建议7-1-2 常量建议使用const定义代替宏。
说明:有的 C 编译器不支持用 const 定义常量,此时只好#define。用 const 定义的常量具有类型,且在调试时也更加方便(可以直接查看变量值)。
建议7-1-3 宏定义中尽量不使用return、goto、continue、break等改变程序流程的语句。
7.2 枚举
【规则 7-2-1】枚举成员不是变量,而是常数,和const定义常变量一样,所以不能对枚举元素进行赋值。
【规则 7-2-2】枚举成员作为常量,定义的时候存储的值按列举顺序依次默认为0,1,2……。当然,声明时候可以修改其存储值,即修改枚举值, 但不可以为负数,如-1,-2等,且枚举值为整数。
【规则 7-2-3】枚举成员不是简单字符串常量,使用的时候无需添加单、双引号。
【规则 7-2-4】枚举成员不可以重复,但是枚举值可以重复。重复枚举值的枚举成员表明它们具有共同性质,所以放在一起。
【规则 7-2-5】一个整数不能直接赋给一个枚举变量,必须强制进行类型转换才能赋值。
例如:
enum weeks day;
day =(weeks)2;
应用案例:
#include<stdio.h>
int main( )
{
enum weekday {sun=1,mon,tue,wed,thu,fri,sat} day; //从1开始
int k;
printf("请输入今天星期几(1--7):");
scanf("%d",&k);
day=(enum weekday)k;
switch(day)
{
case mon:
case tue:
case wed:
case thu:
case fri:
printf("今天上班\n");
break;
case sun:
case sat:
printf("今天休息\n");
break;
default:
printf("输入有误\n");
break;
}
return 0;
}