Hintergrund
Beim Entwurf von binären Dateiformaten wird generell empfohlen, ganze Zahlen in die Netzwerk-Byte-Reihenfolge zu schreiben. Dafür gibt es Makros wie htonhl()
. Aber für ein Format wie WAV wird eigentlich das Little-Endian-Format verwendet.
Frage
Wie schreiben Sie portabel kleine Endian-Werte, unabhängig davon, ob die CPU, auf der Ihr Code läuft, eine Big-Endian- oder Little-Endian-Architektur ist? (Ideen: können die Standardmakros ntohl()
und% co_de Wird% "irgendwie umgekehrt" verwendet? Oder sollte der Code nur Laufzeit testen, wenn er auf einer kleinen oder großen Endian-CPU läuft und den entsprechenden Codepfad auswählt?)
Es geht also nicht wirklich um Dateiformate, Dateiformate waren nur ein Beispiel. Es kann jede Art von Serialisierung sein, bei der ein kleines Endian "auf dem Draht" erforderlich ist, wie beispielsweise ein (häretisches) Netzwerkprotokoll.
C bietet bereits eine Abstraktion über die Endlichkeit des Hosts: die Nummer † oder int †.
Das Erzeugen von Ausgaben in einer gegebenen Endianz kann portabel ausgeführt werden, indem man nicht versucht, clever zu sein: interpretiere einfach die Zahlen als Zahlen und benutze Bit-Verschiebungen, um jedes Byte zu extrahieren:
%Vor%Dann schreiben Sie einfach die Bytes in der von Ihnen gewünschten Reihenfolge.
Wenn Sie Byte-Sequenzen mit einer gewissen Endiannität als Eingabe verwenden, können Sie sie in der Endianlichkeit des Hosts rekonstruieren, indem Sie wiederum Zahlen mit Bit-Operationen konstruieren:
%Vor%† Nur die Repräsentationen von Zahlen als Bytefolgen haben Endianness; Zahlen (d. h. Mengen) nicht.
Tatsächlich funktionieren die MSDN-Funktionen ntohl () und htonl () sind das Gegenteil von einander:
Die htonl-Funktion konvertiert eine u_long vom Host zum TCP / IP-Netzwerkbyte Reihenfolge (die Big-Endian ist).
Die ntohl-Funktion konvertiert einen u_long von der TCP / IP-Netzwerkreihenfolge in den Host Byte-Reihenfolge (das ist Little-Endian auf Intel-Prozessoren).
Ja, Laufzeit-Erkennung von Endianness ist eine sehr vernünftige Sache zu tun, und im Grunde, was irgendein gebrauchsfertiges Makro / irgendeine Funktion irgendwann sowieso machen würde.
Und wenn Sie Little-Big-Endian-Konvertierungen selbst durchführen möchten, sehen Sie sich die Antwort von @ R-Martinho-Fernandes an.
Tags und Links c c++ endianness portability