Endianness tells how multiple byte variables are stored in the RAM or handled in a particular format. In normal cases, endianness will be transparent to the user. That means the programmer do not need to worry about how the variables are handled. Every thing happens at the hardware of the processor or will be managed by the compiler.
But if we are trying to access the value of variable directly from the memory, then there is a problem. For this we should know in what order individual bytes in the variable are kept in memory.
Example Code
1
2
3
4
5
6
7
8
9
10
| #include <stdio.h>
int main()
{
unsigned short int Var1 = 0xAA55;
unsigned char *p = (unsigned char *)&Var1;
printf("Lower byte = 0x%02X\n", *p);
printf("Higher byte = 0x%02X\n", *(p+1));
}
|
In the source code,Var1 is a 2-bytes variable which contains 0xAA55. Now p is declared as pointer to an unsigned character of size 1-byte. Since p is initialized to the address of the variable Var1, it is now pointing to the first memory location which contains Var1. For example(see the figures shown below), if variable Var1 is in the address 0x1035 then it will be occupying the addresses 0x1035 and 0x1036. Depending on the endianness the order in which higher byte and lower bytes are stored in these memory locations. By printing *p we will know what is there in the first address ie, 0x1035 and by printing *(p + 1) we will know what is there in the second memory location.
|
Memory map in case of Little Endian Architecture |
|
Memory map in case of Big Endian Architecture |
Output
Pasted below is the output of the program compiled and executed on my netbook running on
Intel atom processor.
G:\Working\c_programs>gcc EndiannessCheck.c
G:\Working\c_programs>a.exe
Lower byte = 0x55
Higher byte = 0xAA
G:\Working\c_programs>
Here you can see that first byte printed using the pointer p is 0x55 and second byte is 0xAA. Since lower byte lies in the lower address it is Little endian architecture.
Pragmatically this code will mostly work.
ReplyDeleteBut it's important to know that it isn't well defined C as it violates the strict aliasing rules, and so the code optimizer could easily decided to do something unexpected.
It would be better to use a union like this:
union {
unsigned short s;
unsigned char[2] c;
}