You are comparing an unsigned int to a signed char. The semantics of this kind of comparison are counter-intuitive: most binary operations involving signed and unsigned operands are performed on unsigned operands, after converting the signed value to unsigned (if both operands have the same size after promotion). Here are the steps:
- The
signed char value is promoted to an int with the same value -23.
- comparison is to be performed on
int and unsigned int, the common type is unsigned int as defined in the C Standard.
- The
int is converted to an unsigned int with value UINT_MAX - 23, a very large number.
- The comparison is performed on the
unsigned int values: 23 is the smaller value, the comparison evaluates to false.
- The
else branch is evaluated, no is printed.
To make matters worse, if c had been defined as a long, the result would have depended on whether long and int have the same size or not. On Windows, it would print no, whereas on 64 bit Linux, it would print yes.
Never mix signed and unsigned values in comparisons. Enable compiler warnings to prevent this kind of mistake (-Wall or -Weverything). You might as well make all these warnings fatal with -Werror to avoid this kind of ill-fated code entirely.
For a complete reference, read the following sections of the C Standard (C11) under 6.3 Conversions:
- integer promotions are explained in 6.3.1.1 Boolean, characters, and integers.
- operand conversions are detailed in 6.3.1.8 Usual arithmetic conversions.
You can download the latest draft of the C11 Standard from the working group website: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf