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

sin*_*law 8 c c-preprocessor

考虑:

#define TEST(x) x
int arr[2] = TEST({1, 2});
Run Code Online (Sandbox Code Playgroud)

我希望它可以被预处理成 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});
Run Code Online (Sandbox Code Playgroud)

铛3.8.1:

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

我找不到在宏的C语言标准部分(6.10)中特别对待大括号的内容。

为什么会这样?

sin*_*law 9

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

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

#define TEST(x, y) | x | y |
int arr[2] = TEST({1, 2});
Run Code Online (Sandbox Code Playgroud)

预处理为:

int arr[2] = | {1 | 2} |;
Run Code Online (Sandbox Code Playgroud)

第6.10.3.11节:

由最外层匹配括号界定的预处理标记序列形成了函数式宏的参数列表。列表中的各个参数由逗号预处理标记分​​隔,但是匹配的内部括号之间的逗号预处理标记不会分隔参数。如果参数列表中有一些预处理令牌序列,否则它们将充当预处理指令,172)行为未定义。