I was surprised when this for loop failed to run properly:
for (std::size_t i=2; i >= 0; --i)
I figured, okay, probably the final check is if -1 >= 0, and since i is not allowed to be negative, we got a problem. Presumably i is looping around to 2^64 - 1.
However, this for loop does execute:
for (std::size_t i=2; i+1 > 0; --i)
Ignoring std::size_t for a moment; this doesn’t make sense to me from a logical perspective. Both (i+1 > 0) and (i >= 0) will be either true or false for the exact same values of i.
Both will be true if i = {0, 1, 2, …} and false if i = {-1, -2, -3, …}.
What is going on here?
Is it something to do with the implementation of std::size_t or the compiler, or am I just missing something very obvious?
>Solution :
What is going on here?
std::size_t is an unsigned integer type.
i >= 0
All unsigned integers are greater than or equal to 0. There exists no value for which this relation would be false and hence the loop cannot end.
i+1 > 0
An unsigned integer can be 0. Hence this relation can be false and the loop can end. Example:
std::size_t i = 0;
i -= 1;
assert(i+1 == 0);
The value of i that ends the loop is congruent with -1 modulo M, where M is the number of representable values which is 2b where b is the width of the integer type in bits. That number is the greatest representable value i.e. 2b-1.
Your deduction works with whole numbers, but it doesn’t work with modular arithmetic.