1
votes

I am in process of rewriting code from Big Endian Machine to Little Endian machine.

Let's say there is a variable called a, which is a 32 bit integer which holds current timestamp(user request's current timestamp).

In Big Endian machine, right now the code is this way:

uint32 a = current_timestamp_of_user_request;
uint8 arr[3] = {0};
arr[0] = ((a >> (8 * 2)) & 0x000000FF); 
arr[1] = ((a >> (8 * 1)) & 0x000000FF);
arr[2] = ((a >> (8 * 0)) & 0x000000FF);

Now, when I am writing the same logic for little endian machine, can I use the same code(method a), or should I convert the code this way(let's call this method b)?

uint32 a = current_timestamp_of_user_request;
uint32 b = htonl(a);
uint8 arr[3] = {0};
arr[0] = ((b >> (8 * 2)) & 0x000000FF); 
arr[1] = ((b >> (8 * 1)) & 0x000000FF);
arr[2] = ((b >> (8 * 0)) & 0x000000FF);

I wrote this program to verify:

#include<stdio.h>
#include<stdlib.h>


void main() {
    long int a = 3265973637;
    long int b = 0;
    int arr[3] = {0,0,0};

    arr[0] = ((a >> (8 * 2)) & 0x000000FF); 
    arr[1] = ((a >> (8 * 1)) & 0x000000FF);
    arr[2] = ((a >> (8 * 0)) & 0x000000FF);

    printf("arr[0] = %d\t arr[1] = %d\t arr[2] = %d\n", arr[0], arr[1],   arr[2]);

    b = htonl(a);

    arr[0] = ((b >> (8 * 2)) & 0x000000FF); 
    arr[1] = ((b >> (8 * 1)) & 0x000000FF);
    arr[2] = ((b >> (8 * 0)) & 0x000000FF);

    printf("After htonl:\n");
    printf("arr[0] = %d\t arr[1] = %d\t arr[2] = %d\n", arr[0], arr[1],   arr[2]);

}

Results:

Result with little endian machine:

bgl-srtg-lnx11: /scratch/nnandiga/test>./x86
arr[0] = 170     arr[1] = 205    arr[2] = 133
After htonl:
arr[0] = 205     arr[1] = 170    arr[2] = 194

Result with big endian machine:
arr[0] = 170     arr[1] = 205    arr[2] = 133
After htonl:
arr[0] = 170     arr[1] = 205    arr[2] = 133

Looks like without conversion to big endian order, the same logic(without htonl()) gives exact results in filling the array arr. Now, can you please answer should I use htonl() or not if I want the array to be the same in both little endian and big endian machines(little endian result should be exact as big endian result).

2
If the goal is to put the least significant byte of the timestamp in arr[2], then the code should be identical on both machines. The shifting and masking operations in the code are not endian-dependent.user3386109

2 Answers

2
votes

Your code as originally written will do what you want on both big endian and little endian machines.

If for example the value of a is 0x00123456, then 0x12 goes in arr[0], 0x34 goes in arr[1], and 0x56 goes in arr[2]. This occurs regardless of what the endianness of the machine is.

When you use the >> and & operators, they operate on the value of the expression in question, not the representation of that value.

When you call htonl, you change the value to match a particular representation. So on a little endian machine htonl(0x00123456) will result in the value 0x56341200. Then when you operate on that value you get different results.

Where endianness matters is when the representation of a number using multiple bytes is read or written as bytes, i.e. to disk, over a network, or to/from a byte buffer.

For example, if you do this:

uint32_t a = 0x12345678;
...
write(fd, &a, sizeof(a));

Then the four bytes that a consists of are written to the file descriptor (be it a file or a socket) one at a time. A big endian machine will write 0x12, 0x34, 0x56, 0x78 in that order while a little endian machine will write 0x78, 0x56, 0x34, 0x12.

If you want the bytes to be written in a consistent order then you would first call a = htonl(a) before calling write. Then the bytes will always be written as 0x12, 0x34, 0x56, 0x78.

Because your code operates on the value and not the individual bytes of the value, you don't need to worry about endianness.

0
votes

You should use htonl(). On a big-endian machine this does nothing, it just returns the original value. On a little-endian machine it swaps the bytes appropriately. So by using this, you don't have to concern yourself with the endian-ness of the machine, you can use the same code after calling it.