预处理指令在编译前执行,
经过预处理后的程序,
其中一部分非亲自所写的代码会加入到源程序文件中(使用 include 指令),
此外还有符号的替换(使用 define 指令)与条件编译(ifndef 等)。
define 指令(即宏)遵循替换的原则是:
按被替换的字符串直接替换宏标识符。
#define N 3 /*对于编译器而言,这个3是字符串,而不是数字*/
#define Y(n) ((N+1)*n) /*带有参数的宏,其参数也遵循宏替换原则*/
宏不计算表达式——只需记住这一点,那么在考虑宏引起的问题便变得显浅得多了。
带参数的宏 Y,在其使用处的地方展开,表达式 z=2*(N+Y(5+1)) 将展开为:
z = 2 * (3 + ((3+1)*
5+1))
不妨留意一下粗黑体部分,5+1原样替换,5+1 对于编译器而言事实上不过是一条字符串,
替换的过程在编译程序前就已经完成了。这让 5+1 中的 5 先乘了一下,再加1。所求 z 变量值为 48。
使人不解的是结果并不与预计结果相同。
这一般是因为过于相信宏会帮你做更多的事情,甚至觉得在 Y(5+1) 此处帮你算好 5+1 = 6,即理想的 Y(6)。
——这只能算是一厢情愿的想法。
举个差不多相同的例子,有一个宏 Test 被如下声明:
#define Test(N) (N*N)
任意可以编写表达式的地方如此使用该宏:
printf("%d", Test(5+1));
结果是 11 而不是 36。
解决这类尴尬问题的方法是用括号将每个参数都括起来:
#define Test(N) ( (N)*(N) )
如上这样写便能使 Test(5+1) 得到结果 36,
—— 相信大部分人写这个宏的目的是希望结果就是 36,如果不是那你可真是神鬼莫测,让人无法猜出你想干什么了。
使用括号能解决不少问题,包括你讨厌去记的运算符的优先级别,
在程序中适合的地方多多使用也无妨,这样可以抛弃那些令人感觉烦躁枯涩的优先级一边凉快去,
毕竟写程序不是拼谁的记忆力好些,没必要不要为难自己。
[此贴子已经被作者于2006-12-12 15:20:54编辑过]