Unsigned and signed comparison

Solution 1:

Both operands of <= have to be promoted to the same type.

Evidently they are promoted to unsigned int (I don't have the rule from the standard in front of me, I'll look it up in a second). Since (unsigned int)(-1) <= u is false, the loop never executes.

The rule is found in section 5 (expr) of the standard, paragraph 10, which states (I've highlighted the rule which applies here):

Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:

  • If either operand is of scoped enumeration type (7.2), no conversions are performed; if the other operand does not have the same type, the expression is ill-formed.
  • If either operand is of type long double, the other shall be converted to long double.
  • Otherwise, if either operand is double, the other shall be converted to double.
  • Otherwise, if either operand is float, the other shall be converted to float.
  • Otherwise, the integral promotions (4.5) shall be performed on both operands. 60 Then the following rules shall be applied to the promoted operands:
  • If both operands have the same type, no further conversion is needed.
  • Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank shall be converted to the type of the operand with greater rank.
  • Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.
  • Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type.
  • Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

Solution 2:

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.

Solution 3:

Its because -1 is casted as an unsigned int, so the for loop code is never executed.

Try compiling with -Wall -Wextra so you can get the respective warnings (if not getting them so far, and compiling with g++)

http://en.wikipedia.org/wiki/Two's_complement

Solution 4:

This is because i is promoted to an unsigned value before comparison. This will set it to the value of UINT_MAX, which on a 32 bit machine equals to 4294967295. So your loop is essentially the same as:

// will never run
for (i = 4294967295; i <= u; i++) {
    count++;
}