带参数的宏定义的一般形式为:
#define <宏名>(<参数表>) <宏体>
<宏名>:一个标识符
<参数表>:参数可以是一个或多个。多个参数之间用逗号分隔
<宏体>:被替换用的字符串,字符串是由参数表中的各个参数组成的一个或多个表达式
*宏体在调用处直接展开
eg:#define N 2+3
int main ()
{
int n;
n = N*2;
printf ("%d", n);
return 0;
}
答案为8 (2+3*2=8)
假设有这样一个宏定义:
#define exch(x,y) int tmp; tmp=x; x=y; y=tmp;
if (x > y)
exch(x,y);
else
do_something();
根据宏的用法,可得:
if (x > y)
int tmp;
tmp = x;
x = y;
y = tmp;
; // empty statement
else
do_something();
此时,语句tem = x; x = y; y = tmp;明显不在if代码块内。
如果直接在宏定义处加上{},即:
#define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }
那确实是解决了上面的问题,可是还会出现新的问题:
if (x > y)
{
int tmp;
tmp = x;
x = y;
y = tmp;
}; // empty statement
else
do_something();
error: ‘else’ without a previous ‘if’
else 前面的 ;表明之前已经是一个(段)完整的语句了,那么接下来直接用 else 就有语法错误了
但是用上 do{...}while(0) 之后:
if (x > y)
do {
int tmp;
tmp = x;
x = y;
y = tmp;
} while(0);
else
do_something();
为了尽量避免错误,使用do{….}while(0) 把代码块包裹起来,成为一个独立的语法单元,从而不会与上下文发生混 淆。绝大多数的编译器都能够识别do{…}while(0)并进行优化,所以使用这种方法也不会导致程序的性能降低。
参考资料: