Click to See Complete Forum and Search --> : reverse byte order
array[0]=0x11;
array[1]=0x22;
array[3]=0x33;
array[4]=0x44;
unsigned int convert4CharArrayToInt(char array[])
{
int intvar=0;
intvar = * (int *) &array[0];
return intvar;
}
returns: 0x44332211
why does this code reverse the byte order
Strogian
07-29-2005, 12:26 PM
I'd say you should look into "Little-Endian" vs. "Big-Endian" architectures. Wikipedia seems to always be great for these sorts of things:
http://en.wikipedia.org/wiki/Endianness
With that said, you should probably know that what you just did is technically "undefined" in C. Since if you compile that code on various machines, some will print out what you got, and some will print out it in the "normal" order. (And some will even crash!) x86 is just a particularly simple/forgiving architecture, so you can do stuff like that and it will usually chug along. :)
that's a good explanation, but I was wondering why it would behave like this?
is it the compiler, processor's instruction set, that is doing the byte swapping?
is memcpy(&intvar, &array[0],4); a better way?
Strogian
07-29-2005, 05:25 PM
It is the processor's instruction set. When you load an integer from memory into a register, it puts the first byte into the LSB of the register, second byte into the next one up, etc.
The only machine-independent way (in C) for you to set an int variable is to do something like:
intvar = 0x11223344;
Or if you're trying to set it with chars, this would be the best way that I can think of:
long intvar;
intvar = (array[0] << 24) | (array[1] << 16) | (array[2] << 8) | (array[3]);
Notice that intvar is a long, because long is guaranteed to be at least 32 bits, but int is not. (int is only 16-bits on, for instance, 16-bit DOS).
gameboy1234
07-30-2005, 06:05 PM
It's not really the instruction set or even the CPU. (Strogian's right that the "swap" occurs between memory and the CPU registers.) It's just hard wired that way. You could say it's the data bus, but that's not really right either.
There is no swaping really. Print that integer out as single bytes (unsigned char *byteptr = &intvar) and see what you get. You'll get the original order.
On a little endian machine, the high byte is stored last (or, at the highest address in memory). If you did the reverse, ( int arrvars[4]; int intvar; memcpy(arrvars, intvar, 4); ) you'd get the same result. If you dumped memory or your local stack frame, you'd see that intvar is stored as "11 22 33 44" in ascending memory locations.
One more trick is to use network byte order. If you are dealing with a data stream ( as opposed to just storing constants like "intvar = 0x11223344") you can use network byte order conversion macros to convert.
For example:
int streamvar, intvar = 0x11223344;
FILE f;
f = open( "temp", "wb" );
streamvar = htonl( intvar ); /* convert to big endian */
writef( f, streamvar );
This will always write data to a file in big endian format. That is, streamvar will always be stored as "11 22 33 44" in that file. You bypass the CPU and get a little help from the compiler. This works no matter what endian machine you run on (but it does have to be recompiled for each new architecture, of course).
You can also read data from a file, or more importantly from the network, this way. Just use ntohl(). See Beej's guide (http://www.ecst.csuchico.edu/~beej/guide/net/html/structs.html) for more info.