# Endianness

Category | System |
---|

# Overview

*Endianness* is the sequential order in which bytes are arranged when stored in memory.

Bytes are represented in *big-endian* or *little-endian* format.

# Bit Endianness

*Bit endianness* is the convention used to identify the bit positions in a binary number.

## Least Significant Byte

The *least significant byte* (LSB) is the byte containing the least significant bit.

## Most Significant Byte

The *most significant byte* (MSB) is the byte containing the most significant bit.

# Byte Endianness

## Big-endian

Bytes are ordered from the most significant bit to the least significant bit.

The most significant bit is stored first and the least significant bit is stored last.

## Little-endian

Bytes are ordered from the least significant bit to the most significant bit.

The least significant bit is stored first and the most significant bit is stored last.

## Bi-endianness

Some architectures feature a setting which allows for switchable endianness.

# Hardware

Name | Endianness |
---|---|

ARM | bi-endian |

Intel x86 | little-endian |

Intel x86-64 | little-endian |

iOS | little-endian |

PlayStation 3 | big-endian |

PlayStation 4 | little-endian |

PlayStation 5 | little-endian |

Switch | little-endian |

Wii | big-endian |

Wii U | big-endian |

Xbox 360 | big-endian |

Xbox One | little-endian |

Xbox Scarlett | little-endian |

# Byte Swap

When a binary file created on a platform is read on another platform with a different endianness, byte swapping is required.

Byte swap depends on the size of the numbers (ie. a 16-bit value and a 32-bit value require a different byte swap).

The data format must therefore be known to perform endianness conversion.

## Implementations

16-bit integer: swap 2 bytes.

```
uint16_t Swap(uint16_t value)
{
uint16_t result = 0;
result |= (value & 0x00FF) << 8;
result |= (value & 0xFF00) >> 8;
return result;
}
```

32-bit integer: swap 4 bytes.

```
uint32_t Swap(uint32_t value)
{
uint32_t result = 0;
result |= (value & 0x000000FF) << 24;
result |= (value & 0x0000FF00) << 8;
result |= (value & 0x00FF0000) >> 8;
result |= (value & 0xFF000000) >> 24;
return result;
}
```

32-bit floating point:

- Perform a
`reinterpret_cast`

from the floating point value to a 32-bit integer. Swap the integer value and performed another`reinterpret_cast`

to cast the result back to a floating point value.

```
float Swap(float value)
{
uint32_t result = Swap(reinterpret_cast<uint32_t>(value));
return reinterpret_cast<float>(result);
}
```

- Store the floating point value to a temporary union of a float and 32-bit integer and swap the integer value.

```
float Swap(float value)
{
union
{
float f;
uint32_t u;
} swap;
swap.f = x;
swap.u = Swap(swapper.u);
return swap.f;
}
```

## Strategies

There are two strategies when generating binary data.

- Byte swap when building the data for each target platform in the expected endianness.

- Byte swap when loading the data if the endianness of the data is different from the endianness of current platform.

# References

- Endianness, Wikipedia, https://en.wikipedia.org/wiki/Endianness

- Bit numbering, Wikiepdia, https://en.wikipedia.org/wiki/Bit_numbering