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 charvalue is promoted to anintwith the same value-23.
- comparison is to be performed on intandunsigned int, the common type isunsigned intas defined in the C Standard.
- The intis converted to anunsigned intwith valueUINT_MAX - 23, a very large number.
- The comparison is performed on the unsigned intvalues:23is the smaller value, the comparison evaluates to false.
- The elsebranch is evaluated,nois 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