Home > front end >  Why does "for(std::size_t i=2; i >= 0; --i)" fail
Why does "for(std::size_t i=2; i >= 0; --i)" fail

Time:03-23

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 have a problem. Presumably i is looping around to (264 - 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?

CodePudding user response:

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.


This is to some degree a matter of taste, but I recommend following code to loop over numbers (n..0]. It works correctly with both signed and unsigned types:

for (std::size_t i=n; i-- > 0;)

CodePudding user response:

size_t is an unsigned type. In such types, negative values don't exist, but 0-1 is defined to be the value to which adding 1 would give 0 – the maximum representable integer value of size_t.

So, yes:

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.

exactly.

for (std::size_t i=2; i 1 > 0; --i)

So, i reaches 2⁶⁴-1, and you add 1, so you get 0, which is not >0, and your loop exits.

Everything's fine here!

  •  Tags:  
  • c
  • Related