(2)使用宏时,不允许参数发生变化。
宏参数始终是一个比较敏感、容易引发错误的东西。有很多人认为,在某种程度上带参的宏定义与函数有几分类似。但是必须注意它们的区别,正如下面代码片段所示:
- #define SQUARE( a ) ((a) * (a))
- int Square(int a)
- {
- return a*a;
- }
-
- int nValue1 = 10, nValue2 = 10;
- int nSquare1 = SQUARE(nValue1++); // nSquare1=110, nValue1=12
- int nSquare2 = Square(nValue2++);// nSquare2=100, nValue2=11
|
类似的定义,却产生了不同的结果,究其原因还是宏的字符替换问题。正如上面的示例一样,两处的a都被参数nValue1++替换了,所以nValue1自增操作也就被执行了两回。
这就是宏在展开时对其参数的多次取值替换所带来的副作用。为了避免出现这样的副作用,最简单有效的方法就是保证宏参数不发生变化,如下所示。
- #define SQUARE( a ) ((a) * (a))
-
- int nValue1 = 10;
- int nSquare1 = SQUARE(nValue1); // nSquare1=100
- nValue1++; // nValue1=11
|
(3)用大括号将宏所定义的多条表达式括起来。
如果宏定义包含多条表达式,一定要用大括号将其括起来。如果没有这个大括号,宏定义中的多条表达式很有可能只有第一句会被执行,正如下面的代码片段:
- #define CLEAR_CUBE_VALUE( l, w, h )\
- l = 0;\
- w = 0;\
- h = 0;
-
- int i = 0;
- for (i = 0; i < CUBE_ACOUNT; i++)
- CLEAR_CUBE_VALUE( Cubes[i].l, Cubes[i].w, Cubes[i].h );
|
简单的字符替代,并不能保证多条表达式都会放入for循环的循环体内,因为没有将它包围在循环体内的大括号中。正确的做法应该是用大括号将多条表达式括起来,这样就能保证多条表达式全部执行了,如下面的代码片段所示:
- #define CLEAR_CUBE_VALUE( l, w, h )\
- {\
- l = 0;\
- w = 0;\
- h = 0;\
- }
|
请记住:
正确合理使用C语言中的宏,能有效地增强代码的可读性。但是也要遵守一定的规则,避免踏入其中的陷阱:(1)用宏定义表达式时,要使用完备的括号。(2)使用宏时,不允许参数发生变化。(3)用大括号将宏所定义的多条表达式包括起来。
相关链接:
编写高质量代码:改善C++程序的150个建议(连载1)
编写高质量代码:改善C++程序的150个建议(连载2)