以下代码中的两个赋值之间是否存在序列点:
f(f(x=1,1),x=2);
不,没有。在这种情况下,标准确实是模棱两可的。
如果你想确认,gcc 有这个非常酷的选项-Wsequence-point
,在这种情况下,它会警告你操作可能是未定义的
在函数调用的开头和结尾都有序列点。但是,由于函数参数的操作顺序是实现定义的,因此您不能保证f(x=1,1)
将在之前执行x=2
。
另请注意,,
函数调用案例中的 不是引入序列点的逗号运算符。
(草案)标准[6.5.2.2, 10]的相关引用是:
函数指示符、实际参数和实际参数中的子表达式的求值顺序未指定,但在实际调用之前有一个顺序点。
f
因此,对于您的表达式,可以在第二个参数之前评估第一个参数(特别是对 的调用);例如:
(x = 1, 1), f <sp> call, (x = 2), f <sp> call
或者,它可以在第二个参数之后进行评估;例如:
(x = 2), (x = 1, 1), f <sp> call, f <sp> call
[函数调用本身可以(并且很可能会)包含更多的序列点(特别是如果它包含一个return
语句)。]
取决于此,分配之间是否存在序列点。这取决于平台(“未指定”)。
由于在第二种情况下,您x
在两个序列点之间分配了两次,因此您在这样的平台上具有未定义的行为。
有一个序列点,但外部函数参数的评估顺序(及其副作用)仍未定义。该实现可以自由地首先评估内部 f(),其副作用 x=1,或第二个参数,其副作用 x=2。
是的,因为在函数调用之前和之后有一个序列点。
标准的§1.0.17 说:
调用函数时(无论函数是否内联),在对所有函数参数(如果有)求值之后都会有一个序列点,该序列点发生在函数体中的任何表达式或语句执行之前。在复制返回值之后和执行函数外的任何表达式之前还有一个序列点)。
是的,由于逗号操作符,会有一个序列点,但结果仍然是未定义的,因为函数参数的评估未定义,因此无法预测该表达式将生成什么值........表示未定义的行为