我已经用c写了下面的代码。
int x = 8;
x -= --x - x--;
printf("%d", x);它正在打印6,但根据我的逻辑语句应该转换为(从右到左执行)
x = 6-6-8; 所以答案应该是-8。
有人能说出这里发生了什么吗?
发布于 2014-04-12 13:05:47
这是一种未定义的行为。C99标准§6.5µ2表示
在前一个序列点和下一个序列点之间,对象的存储值最多只能通过表达式的求值修改一次。此外,应只读取先验值,以确定要存储的值。
x -= --x - x--;
// equivalent to
x = x - --x - x--;
// postfix decrement has higher precedence than
// prefix decrement. Both have higher precedence than
// subtraction operator. Therefore the above statement is
// equivalent to
x = x - (--x) - (x--);
// the subtraction associates from left to right
// therefore the above statement is parsed as
x = (x - (--x)) - (x--);现在,这里需要注意的重要一点是,-运算符的操作数的求值是相对于彼此的无序的。这意味着不确定首先计算哪个子表达式(x - (--x))或(x--)。
引用来自cppreference.com的这篇优秀文章Order of evaluation -
在C中没有从左到右或从右到左计算的概念,这与运算符的从左到右和从右到左的关联性相混淆:由于operator+的从左到右的关联性,表达式a+b+c被解析为(a + b) + C,但是子表达式c可能在运行时首先(或最后,或同时作为a或b)进行计算。
需要注意的第二件重要事情是,在上面的语句中,由于表达式--x和x--的副作用,x的值被修改了两次。在这两个表达式的求值之间没有序列点,因此不能保证何时会发生副作用。因此,从标准中参考上述部分,它是未定义的行为。
结合上述两点,表达式可以计算为多个值。
int x = 8;
x = (x - (--x)) - (x--);
// (a) (b) (c) name of the sub expressions
// assume (c) is evaluated first and side effect
// takes place immediately. Then (b) is evaluated and
// side effect takes place immediately
x = (6 - (6)) - (8); // -8
// assume (a) is evaluated first, then (b)
// however the side effect of (b) does not take
// place before (c) gets evaluated
x = (8 - (7)) - (7); // -6 这只是两个示例,用来说明语句执行后x可以具有的不同值。这并不意味着x将始终具有所有可能值中的一个值。标准说它是未定义的行为,这意味着该行为是不可预测的。该标准对处理此类情况的实现没有任何要求。未定义的行为意味着任何事情都可能发生,从守护进程飞出你的鼻子到你的硬盘被格式化。您应该始终避免编写调用未定义行为的代码。有关更多详细信息,请阅读此- Undefined Behavior and Sequence Points。
https://stackoverflow.com/questions/23026294
复制相似问题