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

mil*_*des 13 c increment postfix-operator

我不明白为什么下面的代码没有按预期工作:

#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");
}
Run Code Online (Sandbox Code Playgroud)
Terminal: All ones.
Run Code Online (Sandbox Code Playgroud)

当增加循环内的索引时,代码按预期运行:

#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");
}
Run Code Online (Sandbox Code Playgroud)
Terminal: Has a zero.
Run Code Online (Sandbox Code Playgroud)

有人可以解释这两者之间的区别吗?

ana*_*ciu 17

在第一个代码中, when iis 8oneOrZero[i]将计算为false因为oneOrZero[8] == 0,但无论如何i都会增加到9,增量不依赖于表达式的真实性,它会随着表达式的计算而发生多次。

所以很自然地,当i == size被评估时它是9 == 9,这当然是true,因此"All ones"会打印出来给你错误的输出。

在第二个代码i在条件表达式的主体内递增,这意味着它只会在满足条件时递增,因此 when iis 8oneOrZero[i]将评估为false并且i不递增,保留其8值。

在下一行语句i == size将是8 == 9which isfalse并且"Has a zero"将被打印,为您提供正确的输出。


Zet*_*eta 7

当一个迭代索引i也用于检查(与 比较size)时,这是一个典型的逐一错误。不用担心,几乎每个人都会遇到这种情况。

问题在于,即使条件失败,我们已经改变了,结果(i中)oneOrZero[i++]。我们的第二个变体不会落入这个陷阱,因为条件和索引增量是解耦的。

我们可以用一个更简单的例子来复制这种行为:

#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");
}
Run Code Online (Sandbox Code Playgroud)

现在,让我们手动检查条件:

  1. i < size 很好,所以我们继续评估右侧。
  2. i++ 增量 i1(又名size
  3. oneOrZero[0]0,因此条件失败

在这个单次迭代之后i == size,我们打印All ones


将此与其他变体进行比较:

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");
}
Run Code Online (Sandbox Code Playgroud)

再次,我们检查条件:

  1. i < size 很好
  2. oneOrZero[0] == 0,所以我们停下来。
  3. i 永远不会增加

因此i < size,我们打印Has a zero.


请注意,可以将条件更改为

int i = -1;

while(++i < size && oneOrZero[i]);
Run Code Online (Sandbox Code Playgroud)

但这需要仔细的文档。