Values are stored as bits. Hexadecimal format is one way of displaying the value stored in those bits, as is decimal, octal, and binary.
Assuming a 32-bit int
type, the value 102310
is stored as the sequence of bits 00000000 00000000 00000011 11111111
, the hexadecimal representation of which is 0x000003FF
.
A value like this requires multiple bytes for storage. Most systems like x86 store multi-byte values such that the least significant byte comes first, known as "little-endian" order. Other systems store multi-byte values such that the most significant byte comes first, known as "big-endian" order. Assuming our integer 1023
starts at address p
, its bytes will be addressed as shown below in each system:
big-endian: p[0] p[1] p[2] p[3]
+----+----+----+----+
| 00 | 00 | 03 | FF |
+----+----+----+----+
little-endian: p[3] p[2] p[1] p[0]
That's why on your system the display goes from -1 3 0 0
instead of 0 0 3 -1
.
As for why FF
displays as -1
...
There are several different ways to represent signed integer values, but one thing they all have in common is that the leftmost bit is used to indicate sign. If the leftmost bit is 0, the value is positive. If the leftmost bit is 1, the value is negative. Assuming a 3-bit type, they work out like this:
Bits Two's Complement Ones' Complement Sign-Magnitude Unsigned
---- ---------------- ---------------- -------------- --------
000 0 0 0 0
001 1 1 1 1
010 2 2 2 2
011 3 3 3 3
100 -4 -1 -0 4
101 -3 -2 -1 5
110 -2 -3 -2 6
111 -1 -0 -3 7
x86 (along with the vast majority of other systems) uses two's complement to represent signed integer values, so an integer with all bits set is interpreted as -1.
When you use %d
in the printf
call, you're telling printf
to treat the corresponding value as a signed int
and to format it as a sequence of decimal digits. Hence, the byte containing FF
is formatted as -1
on a two's complement system.1
Note that the value stored in x
is 102310
(3ff16
) regardless of how the bytes are ordered or how signed integers are represented. If you print out the hex representation of the value of x
using
printf( "%08X\n", x ); // format output as hexadecimal
it will be displayed as 0x000003FF
, not 0xFF030000
.
- It's actually a little more complicated than that - the value in
p[0]
is first converted from char
to int
, and in order to preserve the sign, that converted value is 0xFFFFFFFF
, which is what actually gets passed to printf
.