Short answer
The hexadecimal constant has type unsigned int
. When converted to signed int
the value becomes -1
. Right-shifting a negative value usually leaves the sign-bit unchanged, so -1 >> 16
is still -1
. A short int
passed to a variadic function gets promoted to signed int
which, when interpreted as an unsigned int
by the %x
conversion specifier, prints out 0xffffffff
.
Long answer
However, your code is broken for a number of reasons.
Integer conversion
int largest_num = 0xFFFFFFFF;
The type of the hexadecimal constant is the first of the following types in which its value can be represented: int
, unsigned int
, long int
, unsigned long int
, long long int
, unsigned long long int
.
If int
has more than 32 bits, you're fine.
If int
has 32 bits or less, The result is implementation-defined (or an implementation-defined signal is raised).
Usually, largest_num
will have all bits set and have the value -1
.
Shifting a negative value
largest_num>>16
If the value of largest_num
is negative, the resulting value is implementation-defined. Usually, the sign bit is left unchanged so that -1
right-shifted is still -1
.
Integer promotion
printf ("0x%.8x\n", (short)(largest_num>>16));
When you pass a short int
to a variadic function, the value will be promoted to int
. A negative value will be preserved when converted to the new type.
However, the "%x"
conversion specifier expects an unsigned int
argument. Because unsigned int
and signed int
are not compatible types, the behaviour of the code is undefined. Usually, the bits of the signed int
is re-interpreted as an unsigned int
, which results in the original value of the hexadecimal constant.
Calling a variadic function
printf(...);
printf()
is a variadic function. Variadic functions (typically) use different calling conventions than ordinary functions. Your code invokes undefined behaviour if you don't have a valid declaration of print()
in scope.
The usual way to provide a declaration for printf()
is to #include <stdio.h>
.
Source: n1570 (the last public draft of the current C standard).