[英]Different results when using increment operator (arr[i++] vs arr[i]; i++;)
I can't get my head around why the code below is not working as expected:我不明白为什么下面的代码没有按预期工作:
#include <stdio.h>
int main() {
int i = 0, size = 9, oneOrZero[] = {1,1,1,1,1,1,1,1,0};
while (i < size && oneOrZero[i++]);
if (i == size) printf("All ones"); else printf("Has a zero");
}
Terminal: All ones.
When incrementing the index inside the loop makes the code run as expected:当增加循环内的索引时,代码按预期运行:
#include <stdio.h>
int main() {
int i = 0, size = 9, oneOrZero[] = {1,1,1,1,1,1,1,1,0};
while (i < size && oneOrZero[i]) {i++;}
if (i == size) printf("All ones"); else printf("Has a zero");
}
Terminal: Has a zero.
Could someone explain the difference between these two?有人可以解释这两者之间的区别吗?
In the first code, when i
is 8
, oneOrZero[i]
will evaluate to false
because oneOrZero[8]
==
0
, but i
will be incremented to 9
anyway, the increment is not dependent on the truthiness of the expression, it will happen as many times as the expression is evaluated.在第一个代码中,当
i
为8
, oneOrZero[i]
将评估为false
因为oneOrZero[8]
==
0
,但无论如何i
都会增加到9
,增量不依赖于表达式的真实性,它会发生的次数与计算表达式的次数相同。
So naturally when i == size
is evaluated it's 9 == 9
, this is, of course, true
, therefore "All ones"
will be printed giving you the wrong output.所以很自然地,当
i == size
被评估时,它是9 == 9
,这当然是true
,因此"All ones"
将被打印出来给你错误的输出。
In the second code i
is incremented inside the body of the conditional expression, this means it will only be incremented if the condition is met, so when i
is 8
, oneOrZero[i]
will evaluate to false
and i
is not incremented, retaining its 8
value.在第二个代码中,
i
在条件表达式的主体内递增,这意味着它只会在满足条件时递增,因此当i
为8
, oneOrZero[i]
将评估为false
并且i
不递增,保留其8
值。
In the next line statement i == size
will be 8 == 9
which is false
and "Has a zero"
will be printed, giving you the correct output.在下一行语句中,
i == size
将是8 == 9
,这是false
并且将打印"Has a zero"
,为您提供正确的输出。
This is a typical off-by-one error when one uses a iteration index i
also for a check (comparison with size
).当使用迭代索引
i
也进行检查(与size
比较)时,这是典型的逐一错误。 No worries, it happens to almost everyone, all the time.不用担心,几乎每个人都会遇到这种情况。
The problem is that, even though the condition failed, we already changed the result ( i
) in oneOrZero[i++]
.问题是,即使条件失败,我们也已经改变了
oneOrZero[i++]
的结果( i
)。 Our second variant doesn't fall into this trap, as the condition and the index increment are decoupled.我们的第二个变体不会落入这个陷阱,因为条件和索引增量是解耦的。
We can replicate that behavior with a simpler example:我们可以用一个更简单的例子来复制这种行为:
#include <stdio.h>
int main() {
int i = 0, size = 1, oneOrZero[] = {0};
while (i < size && oneOrZero[i++]);
if (i == size) printf("All ones"); else printf("Has a zero");
}
Now, let's check the condition by hand:现在,让我们手动检查条件:
i < size
is fine, so we continue to evaluate the right-hand side. i < size
很好,所以我们继续评估右侧。i++
increments i
to 1
(aka size
) i++
增量i
到1
(又名size
)oneOrZero[0]
is 0
, thus the condition fails oneOrZero[0]
是0
,因此条件失败After this single iteration, i == size
, and we print All ones
.在这个单次迭代之后,
i == size
,我们打印All ones
。
Compare this to the other variant:将此与其他变体进行比较:
int main() {
int i = 0, size = 1, oneOrZero[] = {0};
while (i < size && oneOrZero[i]) {i++;}
if (i == size) printf("All ones"); else printf("Has a zero");
}
Again, we check the condition:再次,我们检查条件:
i < size
is fine i < size
很好oneOrZero[0] == 0
, so we stop. oneOrZero[0] == 0
,所以我们停止。i
never gets incremented i
永远不会增加Thus i < size
and we print Has a zero
.因此
i < size
并且我们打印Has a zero
。
Note that it's possible to change the condition into请注意,可以将条件更改为
int i = -1;
while(++i < size && oneOrZero[i]);
but that needs careful documentation.但这需要仔细的文档。
#include <stdio.h>
int main() {
int i = 0, size = 9, oneOrZero[] = {1,1,1,1,1,1,1,1,0};
while (i < size && oneOrZero[i++]);
if (i == size) printf("All ones"); else printf("Has a zero");
}
The above code executes till i = 8
and the first condition i < size
that is 8 < 9
but the second condition oneOrZero[8]
is false
.上面的代码执行直到
i = 8
并且第一个条件i < size
是8 < 9
但第二个条件oneOrZero[8]
为false
。 and anyway i will be incremented to 9. 9 == 9
so it will print "All ones"
will be printed giving you the wrong output.无论如何,我将增加到 9。9
9 == 9
所以它会打印"All ones"
会打印给你错误的输出。
#include <stdio.h>
int main() {
int i = 0, size = 9, oneOrZero[] = {1,1,1,1,1,1,1,1,0};
while (i < size && oneOrZero[i]) {i++;}
if (i == size) printf("All ones"); else printf("Has a zero");
}
The above code executes till i = 8
and evaluates to i < size
and 8 < 9
but oneOrZero[i]
oneOrZero[8] = 0
and evaluates to false
and comes out of the loop and i == size
8 == 9
and prints Has a zero
will be printed, giving you the correct output.上面的代码执行直到
i = 8
并计算为i < size
and 8 < 9
但oneOrZero[i]
oneOrZero[8] = 0
并计算为false
并退出循环和i == size
8 == 9
并打印将打印Has a zero
,为您提供正确的输出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.