Ratgeber · 6 Min Lesezeit

Endianness: Big-Endian und Little-Endian erklärt

Warum dieselbe 32-Bit-Zahl im Speicher unterschiedlich abgelegt wird, je nach Prozessor. Mit Erklärung der historischen Hintergründe und Praxis-Fallen beim Netzwerk-Protokoll.

Wer schon einmal eine binäre Datei in einem Hex-Editor angeschaut hat, kennt das Gefühl: die Bytes stehen nicht in der erwarteten Reihenfolge. Eine 32-Bit-Zahl 0x12345678 liegt im Speicher als 78 56 34 12. Das ist kein Fehler, sondern Little-Endian. Auf einer anderen Maschine würde dieselbe Zahl als 12 34 56 78 stehen, Big-Endian. Der Streit um die richtige Reihenfolge ist fast so alt wie die Computertechnik selbst.

Das Grundprinzip

Eine 16-, 32- oder 64-Bit-Zahl belegt mehrere Bytes im Speicher. Die Frage ist: welches Byte kommt zuerst?

Big-Endian speichert das höchstwertige Byte zuerst, also „groß zuerst”. So, wie wir auch lesen: die 1 in 1234 steht vor der 4. Beispiel für die 32-Bit-Zahl 0x12345678:

Adresse:   100  101  102  103
Inhalt:    12   34   56   78

Little-Endian speichert das niedrigstwertige Byte zuerst, „klein zuerst”. Dieselbe Zahl:

Adresse:   100  101  102  103
Inhalt:    78   56   34   12

Beide Anordnungen kodieren dieselbe Zahl, nur eben mit unterschiedlicher Byte-Reihenfolge.

Wer nutzt was?

ProzessorfamilieEndianness
x86, x86-64 (Intel, AMD)Little-Endian
ARMBi-Endian (meist Little-Endian)
RISC-VBi-Endian (meist Little-Endian)
PowerPCBi-Endian (historisch Big-Endian)
Motorola 68kBig-Endian
SPARCBig-Endian
MIPSBi-Endian

Praktisch dominiert Little-Endian heute den Endkunden-Markt, weil x86 und ARM-Mobile-Chips alle so arbeiten. Netzwerk-Protokolle und Mainframes nutzen oft Big-Endian.

Warum überhaupt zwei Varianten?

Beide Wahlmöglichkeiten haben echte Vorteile.

Vorteil Little-Endian: Die niedrigstwertigen Bits liegen am Anfang. Will man eine 32-Bit-Zahl als 16-Bit-Zahl lesen, kann man einfach die ersten zwei Bytes nehmen, ohne den Pointer anzupassen. Das vereinfacht Casts zwischen unterschiedlichen Integer-Größen.

Vorteil Big-Endian: Die Darstellung entspricht der menschlichen Lese-Reihenfolge. Hex-Dumps sind direkt lesbar, ohne im Kopf umzudrehen. Vergleiche von Zahlen lassen sich byteweise von links nach rechts machen, was bei String-Vergleichen sowieso passiert.

Historisch entstand Little-Endian, weil frühe Mikroprozessoren wie der Intel 8086 Carry-Propagation einfacher implementieren konnten, wenn das niedrigste Byte zuerst kam. Big-Endian hat seine Wurzeln in größeren Maschinen, wo Mainframe-Designer auf Lesbarkeit Wert legten.

Der Name selbst kommt übrigens aus Jonathan Swifts Gullivers Reisen, in dem zwei Königreiche Krieg führen, weil sie sich nicht einigen können, von welcher Seite man ein Frühstücksei aufschlagen sollte.

Network Byte Order

Im Internet-Protokoll-Stack ist die Reihenfolge festgelegt: Big-Endian, auch genannt Network Byte Order. Eine IP-Adresse oder Portnummer wird im TCP/IP-Header immer Big-Endian übertragen.

Auf einem Little-Endian-Rechner heißt das: vor dem Senden müssen Multi-Byte-Werte umgedreht werden. Die BSD-Sockets-API bietet dafür Helfer:

  • htons() — host to network short (16 Bit)
  • htonl() — host to network long (32 Bit)
  • ntohs() — network to host short
  • ntohl() — network to host long

Wer das vergisst, sendet seinen Datenverkehr in der falschen Reihenfolge und wundert sich, warum der Server die Portnummer 1234 als 53764 interpretiert.

Wo Endianness Probleme macht

Binäre Dateiformate. Eine MIDI-Datei ist Big-Endian, eine WAV-Datei Little-Endian, eine TIFF-Datei trägt im Header ein Flag, das die Endianness verrät. Wer einen Parser schreibt, muss die Spezifikation lesen.

Cross-Plattform-Datenaustausch. Wenn ein x86-System eine Struct in eine Datei schreibt und ein SPARC-System sie liest, kommen falsche Werte heraus, sofern nicht explizit konvertiert wird.

Memcpy zwischen Typen. memcpy(&u32_var, byte_array, 4) ergibt unterschiedliche Werte, je nachdem ob das System Little- oder Big-Endian ist. Robuster ist explizites Zusammensetzen: value = (byte_array[0] << 24) | (byte_array[1] << 16) | ..., das ist endianness-unabhängig.

Bit-Field-Layouts in C. Die Reihenfolge der Felder in einer struct { unsigned int a:1; unsigned int b:7; } ist nicht standardisiert. Auf Big- und Little-Endian-Compilern kann sie unterschiedlich sein.

Erkennen, was läuft

Ein kleines C-Snippet zeigt die Endianness des aktuellen Systems:

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

int main(void) {
    uint32_t v = 0x12345678;
    uint8_t *p = (uint8_t *)&v;
    if (p[0] == 0x12) printf("Big-Endian\n");
    else if (p[0] == 0x78) printf("Little-Endian\n");
    else printf("Mixed-Endian (selten)\n");
    return 0;
}

Auf modernen Systemen liefert das fast immer „Little-Endian”.

Mixed-Endian: das vergessene Tier

In historischen Systemen gab es auch Mixed-Endian oder Middle-Endian, etwa bei der PDP-11 von Digital Equipment. Eine 32-Bit-Zahl wurde dort als Wortpaar gespeichert, aber innerhalb jedes Worts in Little-Endian. Das Ergebnis war eine seltsame Reihenfolge wie 34 12 78 56. Solche Anordnungen sind heute praktisch ausgestorben.

Praktische Faustregeln

  • Innerhalb eines Programms ist Endianness meist egal, weil alle Bytes auf derselben Maschine konsistent abgelegt werden.
  • Beim Schreiben in Dateien explizit konvertieren oder das Format dokumentieren.
  • Bei Netzwerk-Übertragung Network Byte Order verwenden.
  • Bei Cast zwischen Pointer-Typen vorsichtig sein, vor allem char* zu int* und umgekehrt.

Verwandte Themen

Tiefer in die Bit-Mechanik: Bitweise Operatoren, Zweierkomplement, und für die ASCII-Folge in mehrbyte-Sequenzen: ASCII und Unicode.

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige