Big Endian 2 little Endian

Gast #5852537
Lesenswert?

Ach du dicker Vater schrieb:
> uint32_t

Du kannst auch mit einem passenden Zeiger aus diesem 
4-Bytes-Speicherblock jedes Byte einzeln rauspicken und ausgeben/irgenwo 
ablegen.
1
    uint32_t num=0x1f2f3f4f;
2
    printf("Zahl: %" PRIx32 "\n\n", num);
3

4
    const size_t ARR_LEN=sizeof(num);
5

6
    for(size_t i=0; i<ARR_LEN; i++){
7
        printf("%" PRIx8 "\t", *((uint8_t*)&num+i));
8
    }
9

10
    puts("");
11

12
    for(size_t i=0; i<ARR_LEN; i++){
13
        printf("%" PRIx8 "\t", *((uint8_t*)&num+(ARR_LEN-1)-i));
14
    }
1
Zahl: 1f2f3f4f
2

3
4f  3f  2f  1f  
4
1f  2f  3f  4f
Gast #5855008
Lesenswert?

Ich mach's so (vor Ewigkeiten irgendwo gefunden):
1
#define SWAP16(x) { register UINT8 aux8;     \
2
        aux8 = (UINT8) ((x) >> 8);           \
3
        (x) = ((x) << 8) | aux8; }
4

5
#define SWAP32(x) { register UINT32 aux32;   \
6
        aux32 = (x);                         \
7
        (x) = (aux32 >> 24 & 0xFF) | (aux32 >> 8 & 0xFF00); \
8
        (x)|= (aux32 << 24 & 0xFF000000) | (aux32 << 8 & 0xFF0000);}
Gast #5855015
Lesenswert?

Rolf M. schrieb:
> Ach du dicker Vater schrieb:
>> Hallo liebes Forum, wie kann ich uint32_t Big Endian nach little Endian
>> konvertieren? Meine Lösung hat jede Menge Schiebereien und Masken.
>
> Kommt drauf an, was du unter "jede Menge" verstehst, aber klingt erstmal
> nicht falsch.

Für zwei Vertauschungsoperationen von je zwei Bytes klingt "jede Menge 
Schiebereien und Masken" nicht nach dem direktesten Weg.

Welche Wortbreite hat der Prozessor?
#5855074
Lesenswert?

Rolf M. schrieb:
> Naja, pro Byte einmal schieben und maskieren halt.

Das muß am Ende nicht unbedingt das Ergebnis sein.

Compiler erkennen z.B., wenn rotiert werden soll. Auch wenn's in C kein 
Statement gibt, um diesen Wunsch direkt hinzuschreiben, wird - so denn 
die Plattform dafür einen Maschinenbefehl hat - im Code aus der 
Maskier-/Schieberei eine Rotate-Instruktion.

Compiler, die schlau genug sind, können genauso gut aus der 
entsprechenden Schiebe- und Maskierkombination eine BSWAP-Instruktion 
basteln (wenn es die auf der Zielplattform gibt).
Gast #5855119
Lesenswert?

"• REV: Converts either:
– 32-bit big-endian data into little-endian data
– or 32-bit little-endian data into big-endian data.
• REV16: Converts either:
– 16-bit big-endian data into little-endian data
– or 16-bit little-endian data into big-endian data.
• REVSH: Converts either:
– 16-bit signed big-endian data into 32-bit signed little-endian data
– 16-bit signed little-endian data into 32-bit signed big-endian data"


#asm(" REV r0,r0");
#asm(" bx lr");

Und aus die Maus.
Gast #5856713
Lesenswert?

Mike schrieb:
> Unbedingt mit den Funktionen: htons(), htonl(), ntohs(), ntohl()

Was ist der Vorteil gegenüber Bitshifts?

Mike schrieb:
> Die Funktionen machen nur was, wo nötig und je nach Compiler/Lib auch
> schön optimiert...

Bitshifts werden genau so vom Compiler optimiert. Außerdem gibt es die 
auch auf Nicht-Posix-Systemen.
Moderator #5856775
Lesenswert?

Mike schrieb:
> Unbedingt mit den Funktionen: htons(), htonl(), ntohs(), ntohl()

Ach du dicker Vater schrieb:
> wie kann ich uint32_t Big Endian nach little Endian konvertieren?

htonl() wäre dann richtig, wenn der TE geschrieben hätte:

  "wie kann ich uint32_t von der internen Darstellung nach der Network-
  Byte-Order konvertieren?"

Da die interne Darstellung nicht unbedingt Big-Endian und die Network-
Byte-Order nicht unbedingt Little-Endian sein muss, ist hier nach einer
Funktion gefragt, die die Byte-Reihenfolge auf jeden Fall umkehrt.
Gast #5856884
Lesenswert?

@Yalu X
>htonl() wäre dann richtig, wenn der TE geschrieben hätte:
>  wie kann ich uint32_t von der internen Darstellung nach der Network-
>  Byte-Order konvertieren?"

Ob der Host-Rechner (CPU) mit Big-Endian oder Little-Endian funzt, hängt 
von der Archidektur ab. Die Network-Byte-Order ist aber IMMER 
Big-Endian: Ergo mit dem 'htonl' Makro hat man unabhängig vom Host 
(portable) eine definierte Byteorder.
Gast #5856897
Lesenswert?

Mike schrieb:
> Die Network-Byte-Order ist aber IMMER
> Big-Endian: Ergo mit dem 'htonl' Makro hat man unabhängig vom Host
> (portable) eine definierte Byteorder.

Es gibt auch Netzwerk-Protokolle mit Little Endian, z.B. CANopen.

Mit Bitshifts kann man ganz genauso eine portable definierte Byte-Order 
erreichen, z.B.:
1
uint16_t parse (const uint8_t* data, size_t length) {
2
  assert (length >= 2);
3
  return data [0] | (((uint16_t) data [1]) << 8);
4
}
Gibt unabhängig von der Host-Order die ersten beiden Bytes des Puffers 
als Little Endian interpretiert zurück.

Allerdings war die Frage des TO überhaupt nicht, von einer bestimmten 
Reihenfolge auf die Host-Reihenfolge umzuwandeln, sondern lediglich, die 
Reihenfolge unabhängig vom Host zu verdrehen.
(Firma: Schweigstill IT) Persönliche Seite #5856911
Lesenswert?

Niklas Gürtler schrieb:
> Es gibt auch Netzwerk-Protokolle mit Little Endian, z.B. CANopen.

Das mag zwar durchaus so sein, aber htonl usw. stammen aber definitiv 
aus dem POSIX-API. Und selbiges umfasst primär die IP-basierte 
Kommunikation auf UNIX-artigen Systemen.

Auch wenn es vermutlich eher zur Polumkehrung des Erdmagnetfeldes kommen 
mag als zur Änderung der Network Byte Order und somit zur Änderung des 
Verhaltens von htonl usw., finde ich es aber auch semantisch ungünstig, 
auf ein Netzwerk-API zu referenzieren, wenn es überhaupt nicht um die 
Kommunikation mittels dieses API geht. Leider betreibt der TE aber 
natürlich die heute übliche Salamitaktik und nennt nicht etwa den 
Kontext, in dem er die Änderung der Endianess durchführen will/muss.

Generell halte ich es aber aber schon für sehr sinnvoll, die Anpassung 
der Endianess einer Bibliotheksfunktion zu überlassen, für die es ggf. 
je nach Prozessorarchitektur optimierte Implementierungen gibt.
Moderator #5856938
Lesenswert?

Mike schrieb:
> @Yalu X
>>htonl() wäre dann richtig, wenn der TE geschrieben hätte:
>>  wie kann ich uint32_t von der internen Darstellung nach der Network-
>>  Byte-Order konvertieren?"
>
> Ob der Host-Rechner (CPU) mit Big-Endian oder Little-Endian funzt, hängt
> von der Archidektur ab.

Das ist schon klar.

Leider meldet sich der TE nicht mehr, um uns mitzuteilen, was er mit der
Konvertierung tatsächlich bezwecken möchte. So bleibt uns als einzige
Information, dass er ein uint32_t von Big-Endian nach Little-Endian
konvertieren möchte. Woher das zu konvertierende uint32_t kommt, und
wohin das konvertierte uint32_t geht, bleibt dabei völlig im Dunkeln.
Unter den gegebenen Umständen muss man davon ausgehen, dass der Input
immer Big-Endian und der Output immer Little-Endian ist. Deswegen
ist ein Byte-Swap (egal, auf welche Weise realisiert), der einzig
richtige Vorschlag.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren