【例15.4】运行如下程序得到一个奇怪的输出结果。请问原因何在?
#include <stdio.h>#define DOUBLE(x) (2*x)void main(){ int i; for(i=0;i<5;i++) printf("2*%d = %d/n",i+1,DOUBLE(i+1));}2*1 = 12*2 = 32*3 = 52*4 = 72*5 = 9
DOUBLE(1)展开为2*1=2,DOUBLE(i+1)展开为2+i,也就是说,C编译看到这个代码首先是将1乘以2,然后再加上i,所以就得到如上结果。
再使用宏时,最好能与定义的格式一样,以免达不到预定目的。例如在这个程序中,如果使用如下格式:
for(i=1;i<6;i++) printf("2*%d = %d/n", i, DOUBLE(i));
就会得到如下的正确输出:
2*1 = 22*2 = 42*3 = 62*4 = 82*5 = 10
当然,也可以将宏定义修改为:
#define DOUBLE(x) (2*(x))
这就保证DOUBLE(i+1)展开为2*i+2*1=2(i+1)。
结论:在宏定义中最好将每个参数都用括号括起来以预防引起与优先级有关的问题。同样,整个结果表达式也应该用括号括起来,以防止当宏用于一个更大一些表达式中可能出现的问题。
可以用“#”号说明要把紧跟它的参数作为字符输出,例如#x,#表示将参数x转换成字符串输出,而不是作为数值输出。假设用k=5作为参数,则在执行宏
#define PRINT(x) printf(#x"=%d/n",x)
时,输出“k=5”。执行宏
#define PRINT(x) printf("<debug >" #x "=%d/n",x)
时,则输出“<debug>k=5”。这种方法常用来作为调试程序时的输出参考信息。
【例15.5】使用宏定义输出语句演示两重循环的执行过程。
#include <stdio.h>#define PRINT(x) printf(#x"=%d/n",x)void main(){ int i=0,j=0; for(i=0;i<2;i++) { PRINT(i); for(j=0;j<2;j++) PRINT(j); }}
程序输出结果如下。
i=0j=0j=1i=1j=0j=1
程序演示了每当i循环一次,j则要相应地循环2次的过程。