宏因为缺少类型检查,所以被有些程序员认为“万恶之首”,但如果宏使用的恰当,还是有一定好处的。下面就将几点宏使用中容易出现的陷阱:
1.用宏定义表达式是,使用完备的括号。
比如:#define ADD(a,b) a+b
初看这样的宏感觉是没问题,但事实却不然,宏只是做一种简单的文本替换,比如你在程序中有这样的调用ADD(a,b)*ADD(c,d),调用者的本意是对(a+b)*(c+d)求值,但实际是这样的
a+b*c+d,有些人可能有点奇怪,为什么是这样的,如果是函数调用就不会出现这种问题,宏与函数是有区别的,我们看下相应的函数是怎么定义的:
value_type ADD(value_type a,value_type b) //value_type定义为基本数据类型
return a+b;
从宏和函数的定义中可以看出,函数的参数有一个类型,而宏没有,这也是为什么宏不做类型检查的一个原因,函数参数既然存在类型,必定在运行期间的某个时刻有自己的内存空间,而宏实在编译预处理的时候就把相关联的做了一个文本替换,所以它的调用跟函数调用存在区别。要避免宏中调用出现的问题,建议:用完备的括号保护宏的各个参数。即:#define ADD(a,b) ((a)+(b)),如果写成是#define ADD(a,b) (a)+(b)的形式,像ADD(a,b)*c这种类似的调用也会出错,所以宏最外面的括号不能少。
2.用大括号将宏定义的多条表达式括起来
有时,我们定义一个宏时,不止简单的一个表达式,例如:
#define SWAP(a,b)\
a ^=b;\
b ^=a;\
a ^=b;
像这样的宏,表面上看起来没什么问题,我在CodeBlocks12.11上面运行了一下,能正确的显示结果,但编译的时间有点久,而我加上大括号,编译相对的时间花费要少,我也不知道什么原因,看了
一下书,书上给的建议是用大括号将宏定义的多条表达式括起来。即:
#define SWAP(a,b){\
{\
a ^=b;\
b ^=a;\
a ^=b;\
}
第一次写博客,语言组织不足之处还望各位见谅。