Ana*_*oly 6 c c89 sequence-points language-lawyer
在准备考试时,ANSI CI遇到了以下问题 -
以下声明是否有效?
如果没有,请进行必要的更改以使其有效.
原始陈述是:test(i++,i++);它无效,因为根据K&R p202,行为未定义
参数的评估顺序未指定
但我可以将其更改为以下声明吗?test(i+=2, i+=3)?
我在K&R或任何其他来源中没有看到这样的记录的问题.但XCode编译它并在没有任何警告的情况下运行.
小智 12
两者都是有效的陈述,即合法的C,在这两种情况下,行为都是未定义的.
Sou*_*osh 12
要添加到现有答案,关键点是声明
test(i+=2, i+=3)
Run Code Online (Sandbox Code Playgroud)
尽可能多地调用未定义的行为
test(i++,i++);
Run Code Online (Sandbox Code Playgroud)
因为,在这两种情况下,在函数参数列表中没有为逗号分隔符安排序列点,因此,您最终会在单个序列点的范围内两次修改同一变量的值.这会调用未定义的行为.
在变更之前和之后,语句在语法上都是有效的.但问题仍然存在.如果要修改参数中的对象,则未指定评估顺序.
C99第6.5.2.2节第10段
函数指示符的评估顺序,实际参数和实际参数中的子表达式是未指定的,但在实际调用之前有一个序列点.
根据第3.4.4节第1段
未指明的行为
使用未指明的值,或本国际标准提供两种或更多种可能性的其他行为,并且在任何情况下都不会对其进行任何进一步的要求.
另一方面,第3.4.3节第1段说明
未定义的行为
使用不可移植或错误的程序结构或错误数据时的行为,本国际标准不要求
在订单或评估的情况下,它可以按任何顺序完成,具体取决于编译器如何生成代码,它可以按任何顺序存储在内存中,也可以通过寄存器传递参数.生成代码后,二进制文件在任何地方都会表现相同.因此,对于一个单独的二进制文件,结果每次都是相同的,但是根据编译器的决定,事情可能会发生变化.
最好的想法是避免任何看似不正确或花哨的东西.如果有疑问,可能是未定义的,未指定的,实现定义的行为.因此,你可以使同样的事情明确无误,确定如下.
test (i, i+1);
i += 2;
Run Code Online (Sandbox Code Playgroud)
要么
test (i+1, i);
i+= 2;
Run Code Online (Sandbox Code Playgroud)
取决于您想要的顺序.