Byte Swap Little Endian and Big Endian

I have run into the Endian (not Indian) debate on numerous occasions. I even wrote an article explaining how to detect the Endianness of your operating system earlier. Simply detecting the endianness of your system is a good starting point in understand Endianess and what it means. In some cases you may need to flip your bytes from big Endian to little Endian, this is especially relevant when dealing with network packets and network programming in C. In network programming sometimes fields in a network packet will have fields that are in little Endian when most of your network fields are in big Endian, and to verify these fields you may need to swap Endianess.

For more information regarding Endianness head to the wiki article. There are also built-in C functions that do this including ntohs, ntohl, htons, htonl, however these functions are not always transferable to another architecture (MIPS, ARM) which also differ in Endianness. Therefore, I have written a few functions to byte swap 16-bit, 32-bit and 64-bit unsigned integers, if you are dealing with signed integers simply modify the functions to be signed.

u_int16_t swap_u16(u_int16_t i) {
    u_int8_t c1, c2;
 
    c1 = i & 255;
    c2 = (i >> 8) & 255;
 
    return (c1 << 8) + c2;
}
 
u_int32_t swap_u32(u_int32_t i) {
    u_int8_t c1, c2, c3, c4;    
 
    c1 = i & 255;
    c2 = (i >> 8) & 255;
    c3 = (i >> 16) & 255;
    c4 = (i >> 24) & 255;
 
    return ((u_int32_t)c1 << 24) + ((u_int32_t)c2 << 16) + ((u_int32_t)c3 << 8) + c4;
}
 
u_int64_t swap_u64(u_int64_t i) {
    u_int8_t c1, c2, c3, c4, c5, c6, c7, c8; 
 
    c1 = i & 255;
    c2 = (i >> 8) & 255;
    c3 = (i >> 16) & 255;
    c4 = (i >> 24) & 255;
    c5 = (i >> 32) & 255;
    c6 = (i >> 40) & 255;
    c7 = (i >> 48) & 255;
    c8 = (i >> 56) & 255;
 
    return ((u_int64_t)c1 << 56) + 
            ((u_int64_t)c2 << 48) + 
            ((u_int64_t)c3 << 40) + 
            ((u_int64_t)c4 << 32) + 
            ((u_int64_t)c5 << 24) + 
            ((u_int64_t)c6 << 16) + 
            ((u_int64_t)c7 << 8) + 
            c8;
}

As you can see these functions simply use a logical & with 0xFF (or 255 in decimal) then bit shift the value to its appropriate location depending on the size of the integer. If you apply the function again it will swap the values to their initial position.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *