Different results when using increment operator (arr[i++] vs arr[i]; i++;)
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.
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.
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.
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.
This is a typical off-by-one error when one uses a iteration index i
also for a check (comparison with 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++]
. 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++
incrementsi
to1
(akasize
)oneOrZero[0]
is0
, thus the condition fails
After this single iteration, i == size
, and we print 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 fineoneOrZero[0] == 0
, so we stop.i
never gets incremented
Thus i < size
and we print 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.