The answer might be compiler dependent but;
What is the expected output of the lines below?
signed char a = -5;
printf("%x \n", (signed short) a);
printf("%x \n", (unsigned short) a);
Would a compiler fill the Most Significant Bits with zeros (0) or ones (1) while casting signed char
to a larger variable? How and when?
P.S. There are other issues too. I tried to run the code below on an online compiler for testing. The outputs were not as I expected. So I added the verbose castings, but it did not work. Why is the output of printf("%x \n", (signed char)b);
4 bytes long instead of 1?
int main()
{
unsigned char a = (unsigned char)5;
signed char b = (signed char)-5;
unsigned short c;
signed short d;
c = (unsigned short)b;
d = (signed short)b;
printf("%x ||| %x ||| %x ||| %x\n", (unsigned char)a, (signed char)b, c, d);
printf("%d ||| %d ||| %d ||| %d\n", a, b, c, d);
printf("%d ||| %d ||| %d ||| %d\n", a, b, (signed char)c, (signed char)d);
return 0;
}
Output:
5 ||| fffffffb ||| fffb ||| fffffffb
5 ||| -5 ||| 65531 ||| -5
5 ||| -5 ||| -5 ||| -5
Conversions between integer types are value preserving when the value being converted is representable in the destination type. signed short
can represent all values representable by signed char
, so this ...
signed char a = -5;
printf("%hd\n", (signed short) a);
... would be expected to output a line containing "-5".
Your code, however, has undefined behavior. The conversion specifier %x
requires the corresponding argument to have type unsigned int
, whereas you are passing a signed short
(converted to int
according to the default argument promotions).
Provided that your implementation uses two's complement representation for signed integers (and I feel safe in asserting that it does), the representation will have sign-extended the original signed char
to the width of a signed short
, and then sign-extended that to the width of a (signed) int
. Thus, one reasonably likely manifestation of the UB in your ...
printf("%x \n", (signed short) a);
... would be to print
fffffffb
The other case is a bit different. Integer conversions where the target type is unsigned and cannot represent the source value are well defined. The source value is converted to the destination type by reducing it modulo the number of representable values in the target type. Thus, if your unsigned short
has 16 value bits then the result of converting -5 to unsigned short
is -5 modulo 65536, which is 65531.
Thus,
printf("%hu\n", (unsigned short) a);
would be expected to print a line containing "65531".
Again, the %x
conversion specifier does not match the type of the corresponding argument ((unsigned short) a
, converted to int
via the default argument promotions), so your printf
has undefined behavior. However, the conversion of a 16-bit unsigned short
to a 32-bit int
on a two's complement system will invole zero-extending the representation of the source, so one reasonably likely manifestation of the UB in your ...
printf("%x \n", (unsigned short) a);
... would be to print
fffb
.