The usual arithmetic conversions will be applied to both the operands of most binary operations on numbers to convert them to a common numeric type before the operation is performed.
The first step of the usual arithmetic conversions is to apply the integer promotions to the numeric operands. This only affects operands whose integer rank is less than that of the type int (and unsigned int). So it will affect the operand types _Bool, char, signed char, unsigned char, short, and unsigned short, and also bit-fields of various widths. The integer promotions do not change the numeric value of the operand, only the type. If int can represent all values of the original lower rank type (as restricted by the width for a bit-field), then the lower rank value will be converted to int, otherwise the lower rank value will be converted to unsigned int:
- The comparison
(signed char)-1 == (unsigned char)255 will be converted to (int)-1 == (int)255 by the integer promotion rules.
- The comparison
(signed int)-1 == (unsigned int)UINT_MAX will be left unchanged by the integer promotion rules.
The second step of the usual arithmetic conversions is to convert the promoted operands to a common numeric type. When one operand has type int and the other operand has type unsigned int, the operand of type int will be converted to unsigned int, which will change negative values to large, positive values:
- The comparison
(signed char)-1 == (unsigned char)255 will be converted to (int)-1 == (int)255 by integer promotion and will remain as (int)-1 == (int)255 after the remaining usual arithmetic conversions. The result of the comparison is 0.
- The comparison
(signed int)-1 == (unsigned int)UINT_MAX will be left unchanged by integer promotion and will be converted to (unsigned int)UINT_MAX == (unsigned int)UINT_MAX by the remaining arithmetic conversions (since (unsigned int)-1 is the same as (unsigned int)UINT_MAX). The result of the comparison is 1.
The second part of OP's question has undefined behavior here:
unsigned d = UINT_MAX;
printf(“%d\n”, d);
The printf format specifier %d expects an argument of type int, but an argument of type unsigned int has been supplied, resulting in UB. However, assuming the compiler passes int arguments in the same way as unsigned int arguments, what is likely to happen is that printf will re-interpret the binary representation of the unsigned int value as an int value. Assuming int has a 2's complement representation with no padding bits, the binary representations of (int)-1 and (unsigned int)UINT_MAX will be identical, so printf will output -1 since it is expecting an int. (Reminder: this is undefined behavior.)
The variadic arguments of the printf call will have the default argument promotions applied. Arguments of type float will be converted to double, and the integer promotions will be applied to arguments of integer type, so:
(signed char)-1 will be converted to (int)-1
(unsigned char)255 will be converted to (int)255
(int)-1 will remain unchanged
(unsigned int)UINT_MAX will remain unchanged, and will result in undefined behavior because printf is expecting an int.
%dworks forint, but not forunsigned. So we don't know what the result - if any - will be.