我在书中读到了这个C programming : A modern approach -
According to C standard statements such as
c = (b=a+2) - (a=1) ;
causes undefined behavior.
但是没有提及原因。我的理解是这样的:
所有变量在序列点之间仅被修改一次。 (所以不应该是UB)
子表达式的求值顺序未定义。 (但这并不意味着它会调用未定义的行为,对吧?)
还有什么原因导致它成为未定义的行为?
最佳答案
1 和 2 完全正确。对于操作数的计算顺序,C 中的大多数运算符都未指定。这意味着 (b=a+2)
或 (a=1)
都可以首先进行评估,并且您无法知道哪个顺序适用于任何给定情况。
此外,如果在两个序列点之间修改变量,则不允许对该变量进行任何其他访问,除了计算要存储在其中的值之外。
C99 在 6.5 中声明了这一点(强调我的):
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.
因此,像 a = a+1
这样的代码是完全定义良好的,而像 a = a++
这样的代码会导致未定义的行为。
这一切都归结为“抽象机器”,它是决定程序执行顺序的规则。将值写入变量会产生副作用,并且 C 标准规定所有副作用必须在下一个序列点之前发生。现在,如果您有多个与同一变量相关的副作用,则无法保证它们将按照彼此相关的顺序进行排序,直到到达下一个序列点。
避免由排序和求值顺序引起的错误的实用建议是保持表达式简单,每行使用尽可能少的运算符和尽可能少的副作用。对于您的原始示例,编写代码的更好方法是:
b = a + 2;
a = 1;
c = b - a;
编译器和人类读者都不会误解上述代码。
仅供记录,C11 有不同的文本,但含义完全相同:
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.
关于c - : c = (b=a+2) - (a=1) ; 的未定义行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25197937/