【问题标题】:How can I use parentheses in C++ macro parameters?如何在 C++ 宏参数中使用括号?
【发布时间】:2025-12-03 03:55:02
【问题描述】:

我需要在宏的实际参数中使用括号,但括号似乎改变了分隔宏参数的逗号的行为。

我让我的预处理器将其输出转储到一个文本文件中,这样我就可以看到它产生了什么。
然后我进行了基本测试以确认行为。

#define MACRO_TEST_1( X , Y ) X && Y

MACRO_TEST_1 ( A , B )
// Desired result: A && B
// Actual result:  A && B

MACRO_TEST_1 ( ( C , D ) )
// Desired result: ( C && D )
// Actual result:  ( C , D ) &&
// Warning: "not enough actual parameters for macro 'MACRO_TEST_1'"

似乎在第一个参数中添加左括号,在第二个参数中添加右括号会导致预处理器将逗号视为第一个参数的 part参数,因此假设我根本没有提供第二个参数。
警告和预处理器输出在&& 之后什么都没有显示,这就是证明。

所以我的问题是,我如何告诉预处理器逗号分隔参数,即使参数中有括号?

我尝试转义括号或逗号,但这没有任何区别。
(结果相同,只是在预处理器输出中插入了转义字符。)

【问题讨论】:

  • 你真的需要用宏来做这个吗?为什么?
  • @FrankPuffer 我不会详细说明。这是一个奇怪的情况,使用旧代码 - 可能是暂时的。我想我可能不得不使用一个鲜为人知的技巧来获得括号,而这正是我暂时需要的。
  • @FrankPuffer 函数不会有同样的问题吗? func(1, 2) 是 2 个参数,func((1, 2)) 只是一个参数。
  • 我不明白你为什么要在调用中添加额外的括号。括号的全部意义是将事物组合在一起。当你用括号包裹一个函数或宏参数时,它就变成了一个单独的参数。
  • @Barmar 我明白了。我的想法是,既然这是我们正在谈论的预处理器,那么通常没有针对此类规则的解决方法吗?我不知道预处理器会施加限制,使某些结果在过去是不可能的……这对我来说似乎很奇怪。

标签: c++ macros escaping c-preprocessor preprocessor-directive


【解决方案1】:

所以我的问题是,我怎样才能告诉预处理器逗号 分隔参数,即使参数有括号 在他们里面?

我认为没有办法,至少在这样的宏实现中。

来自gcc.gnu.org

要调用一个带参数的宏,你可以写下 宏后跟括号中的实际参数列表,分隔 用逗号。

每个参数中的前导和尾随空格都被删除,并且所有 参数标记之间的空格减少为单个 空间。 每个参数中的括号必须平衡;内有逗号 这样的括号不会结束论点。

你不能完全忽略论点;如果一个宏需要两个 参数,其顶层必须有一个逗号 参数列表。

【讨论】:

  • 谢谢。这听起来像是转义字符应该能够合理地改变括号字符的含义的情况。遗憾的是,事实并非如此 - 如果可以转义括号,宏可能会更广泛/更灵活。
  • @Giffyguy 在任何情况下,宏只是 C 的遗留物,对于许多用途来说不够灵活,所以......我们拥有我们所拥有的 :)
【解决方案2】:

我在技术上找到了一个解决方案,虽然很难看。
您必须为括号字符定义符号。

#define OP (
#define CP )

#define MACRO_TEST_1( X , Y ) X && Y

MACRO_TEST_1 ( A , B )
// Desired result: A && B
// Actual result:  A && B

MACRO_TEST_1 ( OP C , D CP )
// Desired result: ( C && D )
// Actual result:  ( C && D )

【讨论】: