使用增量运算符时的不同结果(arr[i++] vs arr[i]; i++;)
Different results when using increment operator (arr[i++] vs arr[i]; i++;)
我不明白为什么下面的代码没有按预期工作:
#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.
当在循环内递增索引时,代码 运行 符合预期:
#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.
谁能解释一下这两者的区别?
在第一个代码中,当 i
为 8
时,oneOrZero[i]
将计算为 false
因为 oneOrZero[8]
==
0
,但是 i
无论如何都会增加到 9
,增量不依赖于表达式的 truthiness,它会随着表达式的计算次数而发生。
所以当 i == size
被评估时自然是 9 == 9
,这当然是 true
,因此将打印 "All ones"
给你错误的输出。
在第二个代码中,i
在条件表达式的主体内部递增,这意味着它只会在满足条件时递增,所以当i
是8
, oneOrZero[i]
将评估为 false
并且 i
不会递增,保留其 8
值。
在下一行语句中 i == size
将是 8 == 9
即 false
并且 "Has a zero"
将被打印,为您提供正确的输出。
这是一个典型的 off-by-one 错误,当使用迭代索引 i
也进行检查时(与 size
比较)。不用担心,几乎每个人都会遇到这种情况。
问题是,即使条件失败,我们已经在 oneOrZero[i++]
中更改了结果 (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");
}
现在,让我们手动检查条件:
i < size
没问题,所以我们继续评价right-hand这边。
i++
增量 i
到 1
(又名 size
)
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");
}
再次检查条件:
i < size
可以
oneOrZero[0] == 0
,所以我们停止。
i
永远不会递增
因此 i < size
我们打印 Has a zero
.
请注意,可以将条件更改为
int i = -1;
while(++i < size && oneOrZero[i]);
但这需要仔细记录。
#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");
}
上面的代码一直执行到i = 8
,第一个条件i < size
是8 < 9
,第二个条件oneOrZero[8]
是false
。无论如何,我将增加到 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");
}
上面的代码执行到 i = 8
并计算为 i < size
和 8 < 9
但 oneOrZero[i]
oneOrZero[8] = 0
并计算为 false
并出现跳出循环
并且 i == size
8 == 9
和打印 Has a zero
将被打印,为您提供正确的输出。
我不明白为什么下面的代码没有按预期工作:
#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.
当在循环内递增索引时,代码 运行 符合预期:
#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.
谁能解释一下这两者的区别?
在第一个代码中,当 i
为 8
时,oneOrZero[i]
将计算为 false
因为 oneOrZero[8]
==
0
,但是 i
无论如何都会增加到 9
,增量不依赖于表达式的 truthiness,它会随着表达式的计算次数而发生。
所以当 i == size
被评估时自然是 9 == 9
,这当然是 true
,因此将打印 "All ones"
给你错误的输出。
在第二个代码中,i
在条件表达式的主体内部递增,这意味着它只会在满足条件时递增,所以当i
是8
, oneOrZero[i]
将评估为 false
并且 i
不会递增,保留其 8
值。
在下一行语句中 i == size
将是 8 == 9
即 false
并且 "Has a zero"
将被打印,为您提供正确的输出。
这是一个典型的 off-by-one 错误,当使用迭代索引 i
也进行检查时(与 size
比较)。不用担心,几乎每个人都会遇到这种情况。
问题是,即使条件失败,我们已经在 oneOrZero[i++]
中更改了结果 (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");
}
现在,让我们手动检查条件:
i < size
没问题,所以我们继续评价right-hand这边。i++
增量i
到1
(又名size
)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");
}
再次检查条件:
i < size
可以oneOrZero[0] == 0
,所以我们停止。i
永远不会递增
因此 i < size
我们打印 Has a zero
.
请注意,可以将条件更改为
int i = -1;
while(++i < size && oneOrZero[i]);
但这需要仔细记录。
#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");
}
上面的代码一直执行到i = 8
,第一个条件i < size
是8 < 9
,第二个条件oneOrZero[8]
是false
。无论如何,我将增加到 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");
}
上面的代码执行到 i = 8
并计算为 i < size
和 8 < 9
但 oneOrZero[i]
oneOrZero[8] = 0
并计算为 false
并出现跳出循环
并且 i == size
8 == 9
和打印 Has a zero
将被打印,为您提供正确的输出。