Jan 11, 2016

C Programming #59: Endianness

C Programming #59: Endianness

We know that all data are stored in memory and all memory are byte addressable. Say we have integer variable initialized to 459,404,006 which takes 4 bytes in memory. 4 byte representation of 459,404,006 in Hexadecimal would be 0x1B61 F2E6. Endianness would explain how would this number 459,404,006 would be stored in memory. And this particular case there is just not one way there are two ways of doing it. These two methods are called.

  • Little endian.
  • Big endian.

This article covers endianness with example-


Little endian

In little endian we store least significant byte in the smallest address.

Taking out earlier example - 0x1B61F2E6

  • E6 - is least significant byte
  • 1B - is most significant byte

Now say we have this integer to stored in address 0x100. Then as we know integer would be stored in 4 bytes in address 0x100 to 0x103

  • 0x100 - E6
  • 0x101 - F2
  • 0x102 - 61
  • 0x103 - 1B

Big endian

In Big endian you store the most significant byte in the smallest address. Same example number 0x1B61F2E6 would be stored in address 0x100 would look as follows.

  • 0x100 - 1B
  • 0x101 - 61
  • 0x102 - F2
  • 0x103 - E6

Now lets implement the same program in C.

#include <stdio.h>

int main()
{
  int var = 0x1B61F2E6;
  char *p;

  printf("value of var is %d (Hex %x), stored at %p\n",
         var, var, &var);

  /* Lets store the &var in char pointer to analyze byte by byte value*/
  p = &var;

  printf("Value at %p is %x\n", p, *p);
  printf("Value at %p is %x\n", p+1, *(p+1));
  printf("Value at %p is %x\n", p+2, *(p+2));
  printf("Value at %p is %x\n", p+3, *(p+3));

  return 0;
}

Output of the above program (If your machine is little endian then your output is)

value of var is 459404006 (Hex 1b61f2e6), stored at 0x7e9934a0
Value at 0x7e9934a0 is e6
Value at 0x7e9934a1 is f2
Value at 0x7e9934a2 is 61
Value at 0x7e9934a3 is 1b

(If your machine is big endian then your output is)

value of var is 459404006 (Hex 1b61f2e6), stored at 0x7e9934a0
Value at 0x7e9934a0 is 1b
Value at 0x7e9934a1 is 61
Value at 0x7e9934a2 is f2
Value at 0x7e9934a3 is e6

When we write a C-program it should work properly both in little endian and big endian machine. Such a program is known as portable code. Whenever possible we should avoiding interpreting data-order. If it cannot be avoided then both implementation should be given in #if. If you are planning to use GNU C extension then code would look as below.

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
/* Little endian implementation should be done here */
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
/* Big endian implementation should be done here */
#else
#error "Unknown endianess"
#endif

Same would be applied to long, long long so on.

Links

No comments :

Post a Comment