简体   繁体   English

使用增量运算符时的不同结果(arr[i++] vs arr[i]; i++;)

[英]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.在第一个代码中,当i8oneOrZero[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在条件表达式的主体内递增,这意味着它只会在满足条件时递增,因此当i8oneOrZero[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:现在,让我们手动检查条件:

  1. i < size is fine, so we continue to evaluate the right-hand side. i < size很好,所以我们继续评估右侧。
  2. i++ increments i to 1 (aka size ) i++增量i1 (又名size
  3. 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:再次,我们检查条件:

  1. i < size is fine i < size很好
  2. oneOrZero[0] == 0 , so we stop. oneOrZero[0] == 0 ,所以我们停止。
  3. 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 < size8 < 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 < 9oneOrZero[i] oneOrZero[8] = 0并计算为false并退出循环和i == size 8 == 9并打印将打印Has a zero ,为您提供正确的输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM