我正在观察不同的行为,我认为它是C标准的一部分clang
和gcc
(在我的mac或linux上的自制软件版本).问题是参数列表中的逗号是否是序列点.clang
解释它,但gcc
不是.
此代码演示了此问题:
#includeint 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标准的副本,但clang
在我看到gcc
解释之前,我非常确定这种行为是正确的.使用该--std=
选项并没有改变我的结果.
ETA
在更好的阅读中,确实可以在/sf/ask/17360801/中回答这个问题:
a,b(§5.18)(在func(a,a ++)中)不是逗号运算符,它只是参数a和a ++之间的分隔符.在这种情况下,如果a被认为是基本类型,则行为是未定义的)
但是,虽然非常有用,但这是一个很长的答案,所以也许留下这个问题将有助于像我这样的其他用户.另外,要迂腐,那个问题是关于C++,而不是C.
参数列表中的逗号不是序列点 - 它们不是术语含义内的逗号运算符.
关于函数调用的标准部分(ISO/IEC 9899:2011)(第6.5.2.2节)说:
3后缀表达式后跟
()
包含可能为空的逗号分隔表达式列表的括号是一个函数调用.后缀表达式表示被调用的函数.表达式列表指定函数的参数.4参数可以是任何完整对象类型的表达式.在准备对函数的调用时,将评估参数,并为每个参数分配相应参数的值.
...
10在评估函数指示符和实际参数之后但在实际调用之前有一个序列点.调用函数(包括其他函数调用)中的每个评估(在执行被调用函数的主体之前或之后没有特别排序)对于被调用函数的执行是不确定地排序的.
(我省略了几个脚注,但内容与讨论没有密切关系.)
没有任何关于在任何特定序列中评估的表达式.
另请注意,逗号运算符会生成单个值.如果您解释:
function(x, y)
由于有一个逗号运算符,该函数只有一个参数 - 值为y
.当然,这不是功能的工作方式.如果你想要一个逗号运算符,你必须使用额外的括号:
function((x, y))
现在function()
使用单个值调用,该值是值y
,但是在评估之后x
评估.这种符号很少使用,尤其是因为它可能会让人感到困惑.