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

问题描述 投票:3回答:2
#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
}

工作良好。

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

c c-preprocessor
2个回答
6
投票

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

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
投票

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.