R..*_*R.. 8 c gcc c99 compound-literals c-preprocessor
在C99中,我们有复合文字,它们可以传递给函数,如:
f((int[2]){ 1, 2 });
Run Code Online (Sandbox Code Playgroud)
但是,如果f不是函数而是函数式宏,gcc barfs由于预处理器解析它不是作为一个参数而是作为两个参数" (int[2]){ 1"和" 2 }".
这是gcc或C标准中的错误吗?如果它是后者,那几乎排除了所有透明使用类似函数的宏,这似乎是一个巨大的缺陷......
编辑:作为一个例子,人们会期望以下是一个符合要求的程序片段:
fgetc((FILE *[2]){ f1, f2 }[i]);
Run Code Online (Sandbox Code Playgroud)
但是因为fgetc可以实现为宏(虽然需要保护其参数而不是多次评估它),但这段代码实际上是不正确的.这对我来说似乎很令人惊讶.
自C89以来,这个"bug"已存在于标准中:
#include <stdio.h>
void function(int a) {
printf("%d\n", a);
}
#define macro(a) do { printf("%d\n", a); } while (0)
int main() {
function(1 ? 1, 2: 3); /* comma operator */
macro(1 ? 1, 2: 3); /* macro argument separator - invalid code */
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我实际上没有查看标准来检查这个解析,我已经采用了gcc的话,但非正式地需要匹配:每个都?胜过运算符优先级和参数列表语法以使第一个语句起作用.第二个没有这样的运气.
这是根据 C 标准,类似于 C++ 中的方式,以下是一个问题:
f(ClassTemplate<X, Y>) // f gets two arguments: 'ClassTemplate<X' and 'Y>'
Run Code Online (Sandbox Code Playgroud)
如果在 C99 中添加一些额外的括号是合法的,您可以使用:
f(((int[2]){ 1, 2 }));
^ ^
Run Code Online (Sandbox Code Playgroud)
来自 C99 §6.10.3/11 的指定此行为的规则如下:
由最外面的匹配括号界定的预处理标记序列形成了类似函数的宏的参数列表。
列表中的各个参数由逗号预处理标记分隔,但匹配内括号之间的逗号预处理标记不分隔参数。