9

在 C99 中,我们有复合文字,它们可以传递给函数,如下所示:

f((int[2]){ 1, 2 });

但是,如果f不是函数而是类似函数的宏,gcc 会拒绝 this,因为预处理器将其解析为两个参数,而不是一个参数,“ (int[2]){ 1”和“ 2 }”。

这是 gcc 或 C 标准中的错误吗?如果是后者,那几乎排除了所有透明使用类似函数的宏,这似乎是一个巨大的缺陷......

编辑:作为一个例子,人们期望以下是一个符合标准的程序片段:

fgetc((FILE *[2]){ f1, f2 }[i]);

但是由于fgetc可以实现为宏(尽管需要保护其参数并且不对其进行多次评估),因此该代码实际上是不正确的。这对我来说似乎很奇怪。

4

3 回答 3

10

自 C89 以来,标准中就存在这个“错误”:

#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;
}

我实际上并没有查看标准来检查这个解析,我已经接受了 gcc 的话,但非正式地需要匹配:每个都?胜过运算符优先级和参数列表语法,以使第一个语句工作。第二个就没有这样的运气了。

于 2011-04-05T22:28:27.757 回答
6

这是根据 C 标准,类似于 C++ 中的方式,以下是一个问题:

f(ClassTemplate<X, Y>) // f gets two arguments:  'ClassTemplate<X' and 'Y>'

如果在 C99 中添加一些额外的括号是合法的,您可以使用:

f(((int[2]){ 1, 2 }));
  ^                ^

来自 C99 §6.10.3/11 的指定此行为的规则如下:

由最外面的匹配括号界定的预处理标记序列形成了类函数宏的参数列表。

列表中的各个参数由逗号预处理标记分​​隔,但匹配内括号之间的逗号预处理标记不分隔参数。

于 2011-04-05T20:35:53.843 回答
1

就它完全是一个错误而言,它与标准有关,而不是 gcc(即,在这方面,我相信 gcc 正在做标准要求的事情)。

于 2011-04-05T20:36:56.493 回答