C中的多表达式宏

liv*_*hak 0 c macros

#define SWAP(a,b) { a^=b ; b^=a ; a^=b; }

if (x < 0)
         SWAP(x,y);
else
         SWAP(y,x);    
Run Code Online (Sandbox Code Playgroud)

我上面给出的代码不起作用.编译时出现以下错误.

trial.c:3:1: error: expected identifier or '(' before 'if'
trial.c:5:1: error: expected identifier or '(' before 'else'
Run Code Online (Sandbox Code Playgroud)

我试图弄清楚它不起作用的确切原因.预处理器按如下方式扩展宏

if (x < 0)
         { 
           x^=y ; 
           y^=x ; 
           x^=y ; 
         }; 
else
         { 
           y^=x ; 
           x^=y ; 
           y^=x ; 
         };
Run Code Online (Sandbox Code Playgroud)

我怀疑花括号末端的分号是导致问题的原因.但我不确定.谁能解释一下?

Kei*_*son 5

如果你想要一个扩展为语句的宏,那么do/while(0)技巧就是你的选择.

但是,如果可能的话,它可以更灵活地将宏扩展为表达式.如果要在语句上下文中使用它,只需添加分号:

#define SWAP(a, b) ( (a)^=(b), (b)^=(a), (a)^=(b) )
Run Code Online (Sandbox Code Playgroud)

原始宏的问题,或者说使用它的方式,是添加的分号创建了一个额外的语句.if- else语句的语法是

if (表达式 ) 语句 else 声明

通过提供一个块{ ... }和一个分号,你和它之间有两个语句.ifelse

do/while(0)技巧解决了分号问题.编写一个扩展为表达式的宏(这并不总是可行)完全避免了它.

更多观察:

你似乎期待SWAP(x, y)SWAP(y, x)做不同的事情.他们的行为应该相同.

xor hack确实允许你在不使用临时的情况下交换变量,但99%的时候只使用临时更有意义.使用临时的一个问题是你必须声明它,这意味着你必须知道类型; 这并不总是可行的.异或黑客的缺点是,如果两个操作数是同一对象(比如,arr[i]arr[j],在这里i ==j),这是行不通的.它只适用于整数.