Consider the following code:
signed a = -1;
unsigned b = UINT_MAX;
printf("%d\n", a==b);
signed char c = -1;
unsigned char d = UCHAR_MAX;
printf("%d\n", c==d);
The result will be:
1
0
char
is based on the actual value, and for an int
is based on the bit representation?signed char a = -1;
unsigned char b = 255;
printf(“%d\n”, a);
printf(“%d\n”, b);
signed c = -1;
unsigned d = UINT_MAX;
printf(“%d\n”, c);
printf(“%d\n”, d);
The result will be:
-1
255
-1
-1
%d
represents char
based on actual value but not int
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
:
(signed char)-1 == (unsigned char)255
will be converted to (int)-1 == (int)255
by the integer promotion rules.(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:
(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
.(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
.