During the comparison (i <= u)
, i
is upgraded to an unsigned integer, and in the process -1 is converted to UINT_MAX.
A conversion of a negative number to an unsigned int will add (UINT_MAX + 1) to that number, so -1 becomes UINT_MAX, -2 becomes UINT_MAX - 1, etc.
If you think about it, one had to be converted to the other in order for the comparison to even work, and as a rule the compiler converts the signed value to unsigned. In this case, of course, it'd make more sense to convert the unsigned value to signed instead, but the compiler can't just decide to follow a different spec based on what you intend. You should explicitly cast the unsigned int to signed (or just have it as signed all along) here.