Many people would find it surprising to see the assertion fail, because -1 is obviously less than 2. However, the return type of
which is an unsigned integer. On 64bit system, it’s probably
unsigned long. Then when
int is compared with
int is converted to
The partial usual arithmetic conversion rule is summarized here, see 18.104.22.168 in C11 for the complete specification.
- return if same type
- otherwise, if signness is the same, smaller integer is upcasted to larger one
- otherwise, if unsigned operand has larger or equal integer, signed integer is converted to unsigned
- otherwise, if sign type can represent all values of the unsigned type, unsigned integer is converted to signed, while preserving the value
- otherwise, both operands are converted to the unsigned version of the signed operand
In the code snippet, rule 3 is applied, for
unsigned long is larger, and
-1 is super larger when interpreted as unsigned, hence the assertion
Now we understand this counterintuitive behavior, but having to struggle with it while programming in C is unbearable. Fortunately, turning on warning flags would expose this kind of madness.