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

为什么gcc不将逗号视为序列点?,c,gcc,clang,C,Gcc,Clang,我观察到在clang和gcc(我的mac或linux上的自制版本)之间,我认为是C标准的一部分的行为有所不同。问题是参数列表中的逗号是否是序列点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[])

我观察到在
clang
gcc
(我的mac或linux上的自制版本)之间,我认为是C标准的一部分的行为有所不同。问题是参数列表中的逗号是否是序列点
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));
}
目前我还没有获得C标准的副本,但是我非常确定
clang
的行为是正确的,直到我看到了
gcc
的解释。使用
--std=
选项根本不会改变我的结果

ETA

更好地阅读,这个问题的答案是:

a,b(§5.18)(在func(a,a++)中,它不是逗号运算符,只是参数a和a++之间的分隔符。如果a被视为基元类型,则该行为未定义)


但是,虽然这很有用,但这是一个很长的答案,所以也许把这个问题留着会帮助像我这样的其他用户。此外,要迂腐,这个问题是关于C++,而不是C.</P> < P>函数的求值顺序是未指定的,所以逗号用作参数的分隔符不是序列点。 6.5.2.2函数调用

10功能指示器的评估顺序,实际 参数,并且实际参数中的子表达式是 未指定,但在实际调用之前有一个序列点

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

#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));
}
#包括
内部整数(整数*v){
*v+=1;
返回1;
}
int main(int argc,char*argv[]){
int x=4;
printf(“结果=%d\n”,(内部(&x),x));
}

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

6.5.2.2函数调用

10功能指示器的评估顺序,实际 参数,并且实际参数中的子表达式是 未指定,但在实际调用之前有一个序列点

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

#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));
}
#包括
内部整数(整数*v){
*v+=1;
返回1;
}
int main(int argc,char*argv[]){
int x=4;
printf(“结果=%d\n”,(内部(&x),x));
}

参数列表中的逗号不是序列点-它们不是术语含义中的逗号运算符

标准(ISO/IEC 9899:2011)中有关函数调用的章节(§6.5.2.2)规定:

^3后缀表达式后跟括号
()
,其中可能包含空的、逗号分隔的表达式列表,这是一个函数调用。后缀表达式表示被调用的函数。表达式列表指定函数的参数

^4参数可以是任何完整对象类型的表达式。在准备调用函数时,将计算参数,并为每个参数指定相应参数的值

^10在函数指示符和实际参数的求值之后但在实际调用之前有一个序列点。调用函数(包括其他函数调用)中在被调用函数体执行之前或之后没有特别排序的每个求值,都是相对于被调用函数的执行不确定排序的

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

对于在任何特定序列中计算的表达式,没有任何内容

还要注意的是,逗号运算符只生成一个值。如果你解释:

function(x, y)
由于有逗号运算符,该函数只有一个参数,
y
的值。当然,函数不是这样工作的。如果需要逗号运算符,则必须使用额外的括号:

function((x, y))

现在用一个值调用
function()
,该值是
y
的值,但在计算
x
之后才进行计算。这种符号很少使用,尤其是因为它可能会让人感到困惑。

参数列表中的逗号不是序列点-它们不是术语含义中的逗号运算符

标准(ISO/IEC 9899:2011)中有关函数调用的章节(§6.5.2.2)规定:

^3后缀表达式后跟括号
()
,其中可能包含空的、逗号分隔的表达式列表,这是一个函数调用。后缀表达式表示被调用的函数。表达式列表指定函数的参数

^4参数可以是任何完整对象类型的表达式。在准备调用函数时,将计算参数,并为每个参数指定相应参数的值

^10在函数指示符和实际参数的求值之后但在实际调用之前有一个序列点。调用函数(包括其他函数调用)中在被调用函数体执行之前或之后没有特别排序的每个求值,都是相对于被调用函数的执行不确定排序的

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

在任何特定的序列中对表达式求值都没有关系

还要注意的是,逗号运算符只生成一个值。如果你解释:

function(x, y)
由于有逗号运算符,该函数只有一个参数,
y
的值。当然,函数不是这样工作的。如果需要逗号运算符,则必须使用额外的括号:

function((x, y))
现在用一个值调用
function()
,它是
y
的值,但是