# Little Endian And Big Endian

In this tutorial, we are going to see the full story of Little Endian And Big Endian.

Normally, Big-endian and little-endian are two formats to store multibyte data types into a computer’s memory. Before that, we should know what is Endian.

## What is Endianness?

The endianness refers to the byte order used by your computer or microcontroller or a machine to read or write a single “machine word” in memory (32-bit machine’s word size is 32-bit and 64-bit machine’s word size is 64-bit ). In other words, The endian will decide how to stores multiple bytes in computer memory. It doesn’t mean, the order of bits inside a byte,  nor the way the computer reads an array of bytes or a file. It’s all about the order of the bytes of a word (multi-byte variable) in memory. Now we will move into Little Endian and Big Endian.

## Little Endian

In Little-endian, LSB (Least significant byte) is stored first or to lower memory address.  Intel x86, Pentium are using this Little endian.

Thus, the little-endian byte order means, when the computer writes a word (Multi Byte) into memory, it begins by writing the Lowest byte to the lowest memory address and continues until it has written the highest byte to the highest memory address. It does this by writing subsequent and ascending memory addresses, no matter the endianness.

## Big Endian

In Big Endian, MSB (Most significant byte) is stored first or to a lower memory address. Big endian is implemented in PowerPC and most networking devices.

The big endian byte order means, when the computer writes a word (Multi Byte) into memory, it begins by writing the highest byte to the lowest memory address and continues until it has written the lowest byte to the highest memory address.

Now we will see the example, then you will understand very easily.

## Example

Consider the number `0x11223344`. This number is written with hexadecimal digits (prefix “`0x`”). Its decimal value is `287454020`. Its consists of 4 bytes: `0x11`, `0x22`, `0x33` and `0x44`.

In this value LSB is `0x44` and MSB is `0x11`.

Now assume that the computer wants to write this number into memory beginning at address 100. This 4-byte value. So it will use the memory address 100, 101, 1o2, 103.

## Big Endian

If the computer uses the Big endian byte order, it begins with the MSB (byte 0x11) and writes it at address 100. Then it writes the next byte 0x22 at address 101, the byte 0x33 at the address of 102, and at last the MSB (byte 0x44) at the last address 103. This results in the following memory content:

Content0x110x220x330x44

## Little Endian

If the computer uses the Little endian byte order, it begins with the LSB (byte 0x44) and writes it at address 100 and then it goes the word backward until it writes the MSB. So it writes the next byte 0x33 at address 101, then it writes 0x22 at address 102, and at last the MSB 0x11 at address 103. Note again that the computer uses sequential ascending addresses, no matter the endianness. This result is the following memory content:

Content0x440x330x220x11

## Program

Now we are going to write a program to see the memory arrangement on our computer. This program will print the memory address and content of our value.

endian.c

```#include <stdio.h>

int main(void)
{
unsigned int value = 0x11223344;
char *r = (char *) &value;
int i;

for(i=0; i<4; i++) {
printf("Address of 0x%x = %d \n", r[i], &r[i]);
}
return 0;
}```

Compile the program

`gcc -o endian endian.c`

Run the program

`./endian`

Output

```Address of 0x44 = 1247158856

If you see the output, 0x44 (LSB) in the Lowest Address and 0x11 (MSB) in the Highest Address. So this system is the Little Endian System.

## Find the Endianness

We can find our system Endianness in many ways. Here I wrote the program in many ways.

### Example 1

```#include <stdio.h>

int main(void)
{
unsigned int value = 0x1;
char *r = (char *) &value;

if (*r == 1)
else
return 0;
}```

Output
```Your system is Little Endian
```

### Example 2

We can find the Endianness of the system using Union. See the below program.

```#include <stdio.h>

union check_endian
{
unsigned int value;
char r;
};

union check_endian endian;

int main(void)
{
endian.value = 0x1;

if (endian.r == 1)
else
return 0;
}```

Output
```Your system is Little Endian
```

## Convert One Endian to Another Endian

Again there are many ways to convert one endian to another endian. Here these programs used to convert from given endianness to another endianness. If the given endianness is little it converts to big endian and vice versa. This code has been written keeping in mind `sizeof(int)` = 4 Bytes.

### Example 1

```#include <stdio.h>

int main(void)
{
int value = 0x11223344;
int converted = 0;

printf("Value Before Converting = 0x%x\n", value);

converted |= ((0xff & value) << 24);
converted |= (((0xff << 8) & value) <<8);
converted |= (((0xff << 16) & value) >> 8);
converted |= (((0xff << 24) & value) >> 24);

printf("Value After Converting = 0x%x\n", converted);
return 0;
}```

Output
```Value Before Converting = 0x11223344
Value After Converting = 0x44332211```

### Example 2

```#include <stdio.h>

int main(void)
{
int value = 0x11223344;
int converted = 0;

printf("Value Before Converting = 0x%x\n", value);

converted |= ((0x000000ff & value) << 24);
converted |= ((0x0000ff00 & value) << 8);
converted |= ((0x00ff0000 & value) >> 8);
converted |= ((0xff000000 & value) >> 24);

printf("Value After Converting = 0x%x\n", converted);
return 0;
}```

Output
```Value Before Converting = 0x11223344
Value After Converting = 0x44332211```

### Example 3

Write a MACRO to convert one Endian to another Endian.

```#include <stdio.h>

#define convert(value) ((0x000000ff & value) << 24) | ((0x0000ff00 & value) << 8) | \
((0x00ff0000 & value) >> 8) | ((0xff000000 & value) >> 24)

int main(void)
{
int value = 0x11223344;
int converted = 0;

printf("Value Before Converting = 0x%x\n", value);

converted = convert(value);

printf("Value After Converting = 0x%x\n", converted);
return 0;
}

```

Output
```Value Before Converting = 0x11223344
Value After Converting = 0x44332211```

## Important of Endian

When you write software that runs on a single machine, usually you do not care for the endianness. When the machine is part of a network, with other machines using different architectures, and the software communicates with others in this network, a transformation must be applied before sending, or after reading data.

However, there are cases when you care for endianness even if your software runs on a single machine. Different file formats use different endianness. For instance, the JPEG format uses big-endian representation, so if you write a program that saves JPEG images and runs on a little-endian machine, you must reverse all the bytes before writing it to disk.

Normally, the endianness of a computer does not play a big role for the programmer, at least as long as the programmer is not doing any network magic in C or some crazy pointer black magic. There are nevertheless cases where the lack of this knowledge can lead to scary bugs. Suppose you are manipulating some binary data in memory, say an array of integers having some meaning. You want to set the first byte of every integer, that is the most significant one, to 0. Because you are a mighty C-wizard, you go on and cast the data array to a pointer to char and iterate over the array like this:

```/* This program should set the most significant byte of
* every integer in the array data to 0.
* The first element should be thus set to 0x00345678 */

#include <stdio.h>

#define SIZE 8
/* some binary data */
unsigned int data[SIZE] =
{
0x12345678, 0x9ABCDEF0, 0X11223344, 0X55667788,
0x99AABBCC, 0xDDEEFF00, 0x11122233, 0x34445556
};

int main(void)
{
/* p is start address of data */
char *p = (char*) data;
size_t i;

for (i = 0; i < sizeof(data); i += 4) {
*(p + i) = 0x0;
}

return 0;
}```

You might think, that p is always pointing to the first (most significant) byte of every integer. You might think that you have the following situation:

 0x12 0x34 0x56 0x78 p

But this is not the case on a little endian machine. On such a machine, p is always pointing to the last byte of every integer (the least significant one) because even though p contains the start address of the first array element, the integer-bytes are reversed in memory, like this:

 0x78 0x56 0x34 0x12 p

And another point is there is something called the “network byte order”. This is how bytes are transferred over the network. This order is the big endian order, the one which most people find natural. This also means that every time an Intel machine receives a word over the network, it must be instructed to reverse it in order to get its actual value.

## Which Endian is better?

When you study about endian, you might think why not only one endian? or why we are not following one endian as a generic?

I will tell you the answer to this question. Both formats, big and little endian have their own advantages and disadvantages. First, we will see those advantages and disadvantages. Then you will find the answer to this question.

In the “Little Endian” form, assembly language instructions for picking up a 1, 2, 4, or longer byte number proceed in exactly the same way for all formats: first, pick up the lowest order byte at offset 0. Also, because of the 1:1 relationship between address offset and byte number (offset 0 is byte 0), multiple precision math routines are correspondingly easy to write.

In the “Big Endian” form, by having the high-order byte come first, you can always test whether the number is positive or negative by looking at the byte at offset zero. You don’t have to know how long the number is, nor do you have to skip over any bytes to find the byte containing the sign information. The numbers are also stored in the order in which they are printed out, so Easier to read hex dumps.

You can also read the below tutorials. 