The portable way to do this (ensuring that you get 0x00 0x00 0x00 0xaf
everywhere) is to use shifts:
unsigned char bytes[4];
unsigned long n = 175;
bytes[0] = (n >> 24) & 0xFF;
bytes[1] = (n >> 16) & 0xFF;
bytes[2] = (n >> 8) & 0xFF;
bytes[3] = n & 0xFF;
The methods using unions and memcpy()
will get a different result on different machines.
The issue you are having is with the printing rather than the conversion. I presume you are using char
rather than unsigned char
, and you are using a line like this to print it:
printf("%x %x %x %x\n", bytes[0], bytes[1], bytes[2], bytes[3]);
When any types narrower than int
are passed to printf
, they are promoted to int
(or unsigned int
, if int
cannot hold all the values of the original type). If char
is signed on your platform, then 0xff
likely does not fit into the range of that type, and it is being set to -1 instead (which has the representation 0xff
on a 2s-complement machine).
-1 is promoted to an int
, and has the representation 0xffffffff
as an int
on your machine, and that is what you see.
Your solution is to either actually use unsigned char
, or else cast to unsigned char
in the printf
statement:
printf("%x %x %x %x\n", (unsigned char)bytes[0],
(unsigned char)bytes[1],
(unsigned char)bytes[2],
(unsigned char)bytes[3]);