Sign in to follow this  
dmatter

question about endianness and shift operators

Recommended Posts

Can someone please explain how the following code works with respect to endianness and what the shift operators do:
    union {
        int i;
        unsigned char c[4];
    };
    
    i = 5;
    //c[0] == 5;
    
    int j = c[0] | c[1]<<8 | c[2]<<16 | c[3]<<24;
    //j == 5 == i
I am assuming that an int is 32-bits and an unsigned char is 8-bits. I don't understand why this works on my machine, surely if c[0] == 5 then it is on the left-most byte of the 4 bytes, but in the assembly of j it is placed as the right-most byte. Obviously I'm not understanding something, I think its how the shift operators work is different to what I imagine. A little confused but any insight is welcome Thanks

Share this post


Link to post
Share on other sites
That code looks fine to me (corresponding to a little-endian architecture, such as the x86). And I doubt your confusion has anything to do with the bitshifts themselves.
Can you elaborate on exactly what you mean by left-most and right-most bytes?

Just to be clear, on a little endian machine the first character in c would be the least significant byte of the integer. So if visualized horizontally with c[0] on the left then you have an order opposite of the "normal" positional system.
So c = { 5, 0, 0, 0 } -> i = 5 and c = { 0, 0, 0, 5 } -> i = 0x05000000.

Share this post


Link to post
Share on other sites
"endianness" is the order that the bytes of a multi-byte value is stored in memory. "Big-endian" means that the bytes are stored in order from highest to lowest significance and "little-endian" means that the bytes are stored in order from lowest to highest significance.

Here is an example that should make things clear. Suppose we store numbers in memory as decimal digits instead of bytes. How would the number 1234 be stored? As big-endian, the digits would be stored from highest to lowest significance: 1, 2, 3, 4. As little-endian, the number would be stored from lowest to highest significance: 4, 3, 2, 1. Note that c[0] would be 1 when stored as big-endian, and 4 when stored as little-endian.

Now, how do we load a number that is stored in the opposite endianness of our machine? If we load it normally, the digits are going to be in the wrong order. To load the number we need to reverse the order of the digits. Suppose in this example, the shift operators << and >> shift left and right 1 digit. We would load a 4 digit number like this: n = c[0] | ( c[1] << 1 ) | (c[2] << 2 ) | ( c[3] << 3 ).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this