CEndianness

Endianness

Endianness describes the order in which a multi-byte value's individual bytes are stored in memory. It only matters for types larger than one byte — int, long, pointers, and so on — since a single char has no ordering to speak of.
Big-Endian vs Little-Endian

Term

Byte order

Used by

Little-endian

Least significant byte stored first (lowest address)

x86, x86-64, and most ARM configurations -- i.e. almost every desktop, laptop, and phone

Big-endian

Most significant byte stored first (lowest address)

Some older architectures (SPARC, older PowerPC), and network protocols by convention

The Same Integer, Two Memory Layouts
Take the 32-bit value 0x12345678. In memory, its four bytes are ordered completely differently depending on the machine:

Text
Value: 0x12345678

Little-endian memory layout (address increasing left to right):
  [0x78] [0x56] [0x34] [0x12]

Big-endian memory layout (address increasing left to right):
  [0x12] [0x34] [0x56] [0x78]

You can observe this directly in C:

C
#include <stdio.h>
#include <stdint.h>

int main(void) {
    uint32_t value = 0x12345678;
    unsigned char *bytes = (unsigned char *)&value;

    for (int i = 0; i < 4; i++) {
        printf("byte[%d] = 0x%02x\n", i, bytes[i]);
    }

    return 0;
}
// On a little-endian machine (e.g. x86-64):
byte[0] = 0x78
byte[1] = 0x56
byte[2] = 0x34
byte[3] = 0x12
Why It Matters
On a single machine running a single program, endianness is completely invisible — every read and write of a multi-byte value goes through the same CPU, using the same byte order consistently, so your arithmetic and comparisons always work correctly. Endianness becomes critical the moment raw bytes leave that one machine and are interpreted somewhere else:
  • Network protocols -- TCP/IP headers define a fixed "network byte order," which is big-endian, regardless of the sender or receiver's native endianness

  • Binary file formats shared across machines -- a file written on a little-endian machine and read on a big-endian one will misinterpret multi-byte fields unless the format explicitly documents (and the reader respects) a byte order

  • Interop with hardware or protocols that mandate a specific byte order (many file formats, some sensors, cryptographic primitives)

Byte-Order Conversion Functions
The standard sockets API (<arpa/inet.h> on POSIX systems) provides a family of conversion functions that translate between a host's native byte order and network byte order:

C
uint32_t htonl(uint32_t hostlong);  // host to network, 32-bit ("long")
uint16_t htons(uint16_t hostshort); // host to network, 16-bit ("short")
uint32_t ntohl(uint32_t netlong);   // network to host, 32-bit
uint16_t ntohs(uint16_t netshort);  // network to host, 16-bit
On a big-endian machine these functions are no-ops; on a little-endian machine (the common case) they swap the byte order. Calling them unconditionally, on every platform, is exactly the point — it makes your network code portable without ever needing an #ifdef for endianness.
Endianness is a property of the CPU, not the C language
C itself does not define or expose endianness directly — it is determined by the target hardware. The only portable way to detect or control byte order from C is through techniques like the one shown above (inspecting individual bytes) or by using the standard conversion functions rather than assuming a particular layout.