short x = -123;
unsigned short y = -123;
printf("%x\n", x>>3);
printf("%x\n", y>>3);
The result was
fffffff0
1ff0
I don't understand the first result because short is 2 bytes but the result was 4 bytes.
short x = -123;
unsigned short y = -123;
printf("%x\n", x>>3);
printf("%x\n", y>>3);
The result was
fffffff0
1ff0
I don't understand the first result because short is 2 bytes but the result was 4 bytes.
The %x
format specifier expects an unsigned int
argument. Passing any other type of argument (even int
) causes undefined behaviour.
You could modify your code to:
printf("%x\n", (unsigned int)(x>>3));
printf("%x\n", (unsigned int)(y>>3));
For x >> 3
, first of all x
undergoes integer promotion. This turns (short)-123
into (int)-123
because promotions are value-preserving.
Then -123 >> 3
causes implementation-defined behaviour. Probably your implementation defines it as an arithmetic right shift on the 2's complement representation in 32-bit integers:
-123: 11111111111111111111111110000101
-123 >> 3: 11111111111111111111111111110000
which is -16
in 2's complement.
Finally, (unsigned int)-16
is defined as meaning UINT_MAX - 15
. 0xFFFFFFFF - 15
gives 0xFFFFFFF0
.
For the unsigned short y = -123;
line, -123
is converted to unsigned short
, giving value for y
on your system of USHRT_MAX - 122
which is 65413
. Then for y >> 3
, this value is promoted to int
, retaining the value 65413
. The definition of right-shift for positive numbers is to divide by 2
that many times. 65413/8
gives 8176
which is 1FF0
in hex.
I don't understand the first result because short is 2 bytes but the result was 4 bytes.
First of all, the >>
operator causes implicit integer promotion of both operands to int
, unless they weren't already of a larger type. The resulting type of the expression is that of the promoted left operand.
Even without the shift operator, all small integer types that are passed to variable-argument functions such as printf, undergo a similar form of implicit integer promotion (the default argument promotion rule) to int
.
This is the reasons why you get 4 bytes.
As for why the values are printed in the way they are, see the answer by M.M. Your code is using the incorrect format specifiers and relies on various forms of poorly-specified behavior, so anything can happen.
Not specifying a modifier for your format in printf
indicate you want the default int
to be printed ( regardless of the length of the value you are passing ).
you can refer to this printf
reference , especially the specifier list to indicate to printf
what is the length you desire.
In your case you wanted a "%hx"
format.