为什么 gcc 不将逗号视为序列点?

Why is gcc not treating comma as a sequence point?

我观察到 clanggcc 之间我认为是 C 标准的一部分的不同行为(我的 mac 或 [=37 上的自制版本=]).问题是参数列表中的逗号是否是序列点。 clang 这样解释,但 gcc 不这样解释。

这段代码演示了这个问题:

#include <stdio.h>

int inner(int *v) {
  *v += 1;
  return 1;
}

int outer(int x, int y) {
  return y;
}

int main(int argc, char *argv[]) {
  int x = 4;
  printf ("result=%d\n", outer(inner(&x), x));
}

结果:

$ clang -o comseq comseq.c && ./comseq
result=5
$ gcc-4.8 -o comseq comseq.c && ./comseq
result=4
$ gcc-5 -o comseq comseq.c && ./comseq
result=4

目前我无法访问 C 标准的副本,但在看到 gcc 的解释之前,我非常确定 clang 的行为是正确的。使用 --std= 选项完全没有改变我的结果。

预计到达时间

在更好的阅读中,确实在 :

中回答了这个问题

a , b (§5.18) (in func(a,a++) , is not a comma operator, it's merely a separator between the arguments a and a++. The behaviour is undefined in that case if a is considered to be a primitive type)

但这虽然非常有用,但却是一个很长的答案,所以也许留下这个问题会对像我这样的其他用户有所帮助。另外,迂腐地说,这个问题是关于C++的,而不是C。

函数参数的求值顺序未指定,因此用作参数分隔符的逗号不是序列点。

N1256 6.5.2.2 函数调用

10 The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.

如果在参数中使用逗号运算符,它将是一个序列点。

#include <stdio.h>

int inner(int *v) {
  *v += 1;
  return 1;
}

int main(int argc, char *argv[]) {
  int x = 4;
  printf ("result=%d\n", (inner(&x), x));
}

参数列表中的逗号不是序列点——它们不是术语意义上的逗号运算符。

标准 (ISO/IEC 9899:2011) 关于函数调用 (§6.5.2.2) 的部分说:

¶3 A postfix expression followed by parentheses () containing a possibly empty, comma- separated list of expressions is a function call. The postfix expression denotes the called function. The list of expressions specifies the arguments to the function.

¶4 An argument may be an expression of any complete object type. In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the corresponding argument.

¶10 There is a sequence point after the evaluations of the function designator and the actual arguments but before the actual call. Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.

(我省略了几个脚注,但内容与讨论无关。)

没有关于以任何特定顺序计算的表达式。

另请注意,逗号运算符会产生单个值。如果你解读:

function(x, y)

因为有一个逗号运算符,该函数将只有一个参数——y 的值。当然,这不是函数的工作方式。如果你想要一个逗号运算符,你必须使用额外的括号:

function((x, y))

现在使用单个值调用 function(),它是 y 的值,但它是在 x 计算之后计算的。这种表示法很少使用,尤其是因为它可能会使人感到困惑。