为什么在定义宏中使用括号会产生错误?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么在定义宏中使用括号会产生错误?相关的知识,希望对你有一定的参考价值。

#define swap(a,b) a = a ^ b; b = a ^ b; a = a ^ b;
int main()
{
    swap(a,b)
}

给出正确的答案。

#define swap(a,b) (a = a ^ b; b = a ^ b; a = a ^ b;)
int main()
{
    swap(a,b)
}

出现编译错误:“expected')'before';'令牌”

#define swap(a,b) ({a = a ^ b; b = a ^ b; a = a ^ b;})
int main()
{
    swap(a,b); //note the semicolon at the end, without that the compiler gives an error
}

工作良好。

现在我的困惑是为什么第二个不起作用?我认为它应该完美。其次,为什么我需要在第三个宏调用结束时加一个分号?

答案

如果你展开宏,它们中的三个看起来像这样:

a = a ^ b; b = a ^ b; a = a ^ b;
(a = a ^ b; b = a ^ b; a = a ^ b;)
({a = a ^ b; b = a ^ b; a = a ^ b;});

第一个很好。第二个是语法错误:您不能用括号括起多个语句。这不是一件事。第三个使用名为statement expressions的GCC扩展。您可以使用({ ... })将一组语句包围起来,将其视为表达式。

请注意,在宏中具有多个语句的标准习惯用法是do { ... } while (0) loop with no trailing semi-colon

#define swap(a,b) do { a = a ^ b; b = a ^ b; a = a ^ b; } while (0)
另一答案

预处理器用字符串替换宏定义,然后编译生成的源代码。对于示例2,您得到的源代码将是:

int main()
{
    (a = a ^ b; b = a ^ b; a = a ^ b;)
}

那是无效的C代码;这就是你的编译器抱怨的原因。这也应该回答你的第二个问题。

尝试使用gcc -E mycode.c-E告诉gcc在预处理器运行后停止编译过程。

以上是关于为什么在定义宏中使用括号会产生错误?的主要内容,如果未能解决你的问题,请参考以下文章

宏中的波浪号 (~) 是啥意思?

我们可以删除 C 宏定义中参数周围的括号吗?

为啥用三元运算符来定义宏中的 1 和 0?

在 MSVC 中处理宏中的额外括号

前端面试之立即执行函数

在宏中过度使用会损害性能吗?