#define SwapByte4(ldata) \
(((ldata & 0x000000FF) << 24) | \
((ldata & 0x0000FF00) << 8) | \
((ldata & 0x00FF0000) >> 8) | \
((ldata & 0xFF000000) >> 24))
What does that 0x000000FF represent? I know that decimal 15 is represented in hex as F, but why is it << 24?
0xff is a number represented in the hexadecimal numeral system (base 16). It's composed of two F numbers in hex. As we know, F in hex is equivalent to 1111 in the binary numeral system. So, 0xff in binary is 11111111.
Well, 0xff is the hexadecimal number FF which has a integer value of 255. And the binary representation of FF is 00000000000000000000000011111111 (under the 32-bit integer). The & operator performs a bitwise AND operation.
0xff means "the hexadecimal number ff " - in other words, the integer 255 , which has the binary representation 00000000000000000000000011111111 (when using 32-bit integers). The & operator performs a bitwise AND operation.
0x000000FF is the hexadecimal representation of blue color. Performing a bitwise AND between integerCode and 0x000000FF filters the blue bits from the integerCode and assigns it to float b. Similarly 0x0000FF00 is the hex of green and 0x00FF0000 is the hex of red. Notice the shifting of FF between the three hex values.
Here is a hex value, 0x12345678, written as binary, and annotated with some bit positions:
|31 24|23 16|15 8|7 bit 0| +---------------+---------------+---------------+---------------+ |0 0 0 1 0 0 1 0|0 0 1 1 0 1 0 0|0 1 0 1 0 1 1 0|0 1 1 1 1 0 0 0| +---------------+---------------+---------------+---------------+
...and here is 0x000000FF:
+---------------+---------------+---------------+---------------+ |0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|1 1 1 1 1 1 1 1| +---------------+---------------+---------------+---------------+
So a bitwise AND selects just the bottom 8 bits of the original value:
+---------------+---------------+---------------+---------------+ |0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 1 1 1 1 0 0 0| +---------------+---------------+---------------+---------------+
...and shifting it left by 24 bits moves it from the bottom 8 bits to the top:
+---------------+---------------+---------------+---------------+ |0 1 1 1 1 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0| +---------------+---------------+---------------+---------------+
...which is 0x78000000 in hex.
The other parts work on the remaining 8-bit portions of the input:
0x12345678 & 0x000000FF ---------- 0x00000078 << 24 = 0x78000000 (as shown above) 0x12345678 & 0x0000FF00 ---------- 0x00005600 << 8 = 0x00560000 0x12345678 & 0x00FF0000 ---------- 0x00340000 >> 8 = 0x00003400 0x12345678 & 0x00000000 ---------- 0x12000000 >> 24 = 0x00000012 | ---------- 0x78563412
so the overall effect is to consider the 32-bit value ldata
as a sequence of four 8-bit bytes, and reverse their order.
This kind of code tends to be used to swap things between big endian and little endian format. There is also a little trick that will convert a word in some known format (lets say, little endian) into whatever endianness the current machine happens to be, and vice versa. That would go something like this:
unsigned long littleEndian;
unsigned char* littleBytes = &littleEndian;
unsigned long result = 0;
for (i = 0; i < 4; i++)
result += unsigned long(littleBytes[i]) << (8 * i);
This works (assuming I haven't messed it up) because regardless of how bytes are actually stored, shift left is guaranteed to shift towards more significant bits. Converting to a char* allows you to access the bytes in the order they are actually stored in memory. Using this trick you don't need to detect the machine endianness to read/write stuff in a known format. Admittedly you could also just use the standard functions (hton etc.) :P
(Note: You have to be a little careful and cast the char before shifting, otherwise it just overflows all over your shoes. Also, += isn't the only option, |= would probably make more sense but might be less clear if you aren't used to it, I'm not sure)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With