为什么C宏调用会吃掉花括号?

时间:2019-03-27 12:12:43

标签: c c-preprocessor

考虑:

#define TEST(x) x
int arr[2] = TEST({1, 2});

我希望它会被预处理成int arr[2] = {1, 2};

相反,gcc和clang都抱怨。 gcc 7.3.0:

./test.c:2:25: error: macro "TEST" passed 2 arguments, but takes just 1
 int arr[2] = TEST({1, 2});

c声3.8.1:

./test.c:2:23: error: too many arguments provided to function-like macro invocation
int arr[2] = TEST({1, 2});

在宏的C语言标准部分(6.10)中,我找不到任何对花括号进行特殊处理的提及。

为什么会这样?

1 个答案:

答案 0 :(得分:9)

原因是调用被逗号分隔以查找参数,而忽略了诸如{和}之类的任何字符(请参见下文,了解标准引用)。只有普通的parens被特殊对待。

因此TEST({1, 2})被解释为传递了两个参数{12}。 确实:

#define TEST(x, y) | x | y |
int arr[2] = TEST({1, 2});

已预处理为:

int arr[2] = | {1 | 2} |;

第6.10.3.11节:

  

以最外面的匹配括号为界的预处理令牌的序列   形成函数式宏的参数列表。内的个别论点   该列表由逗号预处理令牌分隔,但逗号预处理令牌   匹配的内括号之间不要将参数分开。如果有序列   在参数列表中预处理令牌,否则将充当   预处理指令172)行为未定义。