3

众所周知,这循环通过零:

while (x-- > 0) { /* also known as x --> 0 */
  printf("x = %d\n", x);
}

x = x--会产生未定义的行为


这两个例子都需要一些“返回”值x--,我猜这不存在。怎么可能有x-- > 0定义但x = x--没有定义?

4

5 回答 5

19

因为在x = x--您修改x两次的值时没有插入序列点。所以没有定义操作的顺序。中x-- > 0的值x被修改一次,并且明确定义评估的结果x--将是x减量前的值。

于 2011-02-07T17:28:41.373 回答
7

我不知道您从哪里得到关于“需要一些 x-- 的'返回'值,它不存在”的想法。首先,您的意思并不完全清楚。其次,不管你的意思是什么,这似乎与x = x--.

x = x--产生未定义的行为,因为它尝试在x没有中间序列点的情况下修改两次。这里不涉及任何“返回值”的“需要”。

潜在的问题x = x--是它有两个副作用,在未定义的时刻以未定义的顺序发生。赋值运算符引入了一个副作用。后缀运算符引入了另一个副作用--。两种副作用都试图修改相同的变量x并且通常相互矛盾。这就是为什么在这种情况下的行为在法律上被宣布为未定义的原因。

例如,如果原始值为xwas 5,那么您的表达式需要x同时成为4(递减的副作用)和5(赋值的副作用)。不用说,不可能x同时成为45

尽管UB 发生不需要这样一个直接的矛盾(如4vs )。5每次你有两个副作用在没有干预序列点的情况下击中同一个变量时,行为是未定义的,即使这些副作用试图放入变量中的值匹配。

于 2011-02-07T17:33:29.157 回答
3

为了理解这一点,您需要对序列点有一个基本的了解。请参阅此链接:http ://en.wikipedia.org/wiki/Sequence_point

对于=操作符而言,没有序列点,因此无法保证 的值x在再次分配给 之前会被修改x

当您在 while 循环中检查条件时x-- > 0x--会评估并在关系运算符评估中使用该值,因此不会出现未定义的行为,因为x只修改一次。

于 2011-08-07T07:11:37.187 回答
2

只是为了在其他答案中添加一些内容,请尝试阅读有关序列点的维基百科页面。

于 2011-02-07T17:43:24.947 回答
1

我建议阅读https://stackoverflow.com/a/21671069/258418。如果您将=不是序列点的内容放在一起,并且编译器可以自由交错操作,只要它们与您链接的答案没有被序列点分隔,您就会看到以下两个序列是合法的:

load i to reg
increment i
assign reg to i
=> i has previous value of i

load i to reg
assign reg to i
increment i
=> i has value of previous value of i + 1

一般来说:避免在一个表达式中两次分配(这包括通过前/后 ++/-- 修改)相同的变量。

于 2015-07-01T12:27:13.357 回答