Hängt die Bitverschiebung von der Endianness ab?

Lesezeit: 1 Minute

Benutzeravatar von Sandeep Singh
Sandeep Singh

Angenommen, ich habe die Nummer 'numb'=1025 [00000000 00000000 00000100 00000001] repräsentiert:

Auf Little-Endian-Maschine:

00000001 00000100 00000000 00000000

Auf Big-Endian-Maschine:

00000000 00000000 00000100 00000001

Wenn ich nun die Linksverschiebung auf 10 Bits anwende (dh: numb <<= 10), sollte ich Folgendes haben:

[A] Auf Little-Endian-Maschine:

Wie ich in GDB bemerkt habe, macht Little Endian die Linksverschiebung in 3 Schritten: [I have shown ‘3’ Steps to better understand the processing only]

  1. Behandle die Nr. in Big-Endian-Konvention:

    00000000        00000000        00000100    00000001
    
  2. Links-Shift anwenden:

    00000000        00010000        00000100        00000000
    
  3. Stellen Sie das Ergebnis wieder in Little-Endian dar:

    00000000        00000100        00010000        00000000 
    

[B]. Auf Big-Endian-Maschine:

00000000        00010000        00000100        00000000

Meine Frage ist:

Wenn ich direkt eine Linksverschiebung auf die Little-Endian-Konvention anwende, sollte es Folgendes geben:

numb:

00000001 00000100 00000000 00000000

numb << 10:

00010000 00000000 00000000 00000000

Aber eigentlich gibt es:

00000000        00000100        00010000        00000000 

Um nur das zweite Ergebnis zu erzielen, habe ich oben drei hypothetische Schritte gezeigt.

Bitte erklären Sie mir, warum die beiden obigen Ergebnisse unterschiedlich sind: Das tatsächliche Ergebnis von numb << 10 ist anders als das erwartete Ergebnis.

Carls Benutzeravatar
Carl

Endianness ist die Art und Weise, wie Werte im Speicher gespeichert werden. Wenn sie in den Prozessor geladen wird, arbeitet die Bitverschiebungsinstruktion ungeachtet der Endianness mit dem Wert im Register des Prozessors. Daher ist das Laden vom Speicher in den Prozessor das Äquivalent zum Konvertieren in Big Endian, die Verschiebungsoperation kommt als nächstes und dann wird der neue Wert zurück in den Speicher gespeichert, wo die Byte-Reihenfolge Little Endian wieder wirksam wird.

Update, danke an @jww: Auf PowerPC sind die Vektorverschiebungen und -drehungen Endian-sensitiv. Sie können einen Wert in einem Vektorregister haben und eine Verschiebung führt zu unterschiedlichen Ergebnissen bei Little-Endian und Big-Endian.

  • Danke für die Erklärung. Können Sie mir bitte eine Referenz vorschlagen, wo ich solche Feinheiten besser verstehen kann.

    – Sandeep Singh

    26. August 2011 um 1:10 Uhr

  • Das Beste, um Endianness zu verstehen, ist, es auf einer eingebetteten Ebene wirklich auf verschiedenen Architekturen zu verwenden. Ich könnte Sie jedoch auf diese beiden Artikel verweisen: codeproject.com/KB/cpp/endianness.aspx und ibm.com/developerworks/aix/library/au-endianc/…

    – Carl

    4. September 2011 um 23:39 Uhr

  • Mein Code funktioniert also unabhängig von Endian?! das ist toll! Ich war SO besorgt, dass ich meinen Code bis zur Hölle und zurück hacken müsste!

    – MarcusJ

    2. Mai 2016 um 5:00 Uhr

  • @MarcusJ: Nicht unbedingt. Wenn Sie beispielsweise 4 Bytes aus einer Datei lesen, die eine 32-Bit-Ganzzahl darstellen, müssen Sie die Endianness der gelesenen Daten in Verbindung mit der Endianness des Systems berücksichtigen, das die Daten empfängt, um sie richtig zu interpretieren die Daten.

    – Carl

    2. Juni 2016 um 6:52 Uhr

  • Auf PowerPC sind die Vektorverschiebungen und -drehungen Endian-empfindlich. Sie können einen Wert in einem Vektorregister haben und eine Verschiebung führt zu unterschiedlichen Ergebnissen bei Little-Endian und Big-Endian.

    – jww

    14. März 2018 um 16:55 Uhr

Nein, Bitshift ist wie jeder andere Teil von C in Bezug auf definiert Werte, keine Darstellungen. Linksverschiebung um 1 ist Multiplikation mit 2, Rechtsverschiebung ist Division. (Wie immer, wenn Sie bitweise Operationen verwenden, achten Sie auf Vorzeichen. Bei ganzzahligen Typen ohne Vorzeichen ist alles am besten definiert.)

  • Dies gilt grundsätzlich für ganzzahlige Arithmetik, aber C bietet viele Fälle von darstellungsabhängigem Verhalten.

    – Edmund

    25. August 2011 um 3:44 Uhr

  • @Edmund: Hm … vor allem ist die Implementierung der Vorzeichen nicht angegeben, und als Folge davon ist das Verhalten von bitweisen Operationen (wie Rechtsverschiebung) und von Modulo und Division eine Implementierung, die für negative Ganzzahlen definiert ist. Welche anderen Dinge haben Sie im Sinn, die von der Implementierung bestimmt werden?

    – Kerrek SB

    25. August 2011 um 10:24 Uhr

  • @KerrekSB leider sind sie nicht für negative Ganzzahlen implementiert. Sie sind in C89 nicht spezifiziert und in C99+ nicht definiert, was eine sehr schlechte Idee war.

    – Paolo Bonzini

    1. Januar 2016 um 21:48 Uhr

  • @PaoloBonzini: Ja, guter Punkt. Eigentlich ist das sogar noch besser, da es den Punkt verstärkt, dass die Verschiebungsoperationen in Form von Werten definiert sind, möglicherweise undefiniert sind, wenn das Ergebnis nicht darstellbar ist, und dass Spekulationen über die zugrunde liegende Darstellung nicht helfen.

    – Kerrek SB

    1. Januar 2016 um 21:56 Uhr

  • @KerrekSB: Die Sache ist, dass jeder tatsächlich eine Linksverschiebung braucht, um je nach Fall sowohl als Werte als auch als Repräsentation dargestellt zu werden. Und die Verwendung von Ganzzahlen ohne Vorzeichen kann beispielsweise andere Probleme verursachen x &= -1u << 20 wird höchstwahrscheinlich falsch sein, wenn x ist 64-bit und int ist 32-Bit. Aus diesem Grund verspricht GCC, signierte Verschiebungen niemals als undefiniert oder gar nicht spezifiziert zu behandeln.

    – Paolo Bonzini

    7. Januar 2016 um 15:10 Uhr

Benutzeravatar von Rick
Rick

Obwohl die akzeptierte Antwort darauf hinweist, dass Endianess ein Konzept aus der Erinnerungsansicht ist. Aber ich glaube nicht, dass das die Frage direkt beantwortet.

Einige Antworten sagen mir das bitweise Operationen hängen nicht von Endianness ab, und der Prozessor kann die Bytes auf andere Weise darstellen. Wie auch immer, es geht darum, dass Endianess abstrahiert wird.

Aber wenn wir zum Beispiel einige bitweise Berechnungen auf dem Papier durchführen, müssen Sie dann nicht erst die Endianität angeben? Meistens wählen wir implizit eine Endianess.

Angenommen, wir haben eine Codezeile wie diese

0x1F & 0xEF

Wie würden Sie das Ergebnis von Hand auf einem Papier berechnen?

  MSB   0001 1111  LSB
        1110 1111
result: 0000 1111

Hier verwenden wir also ein Big-Endian-Format, um die Berechnung durchzuführen. Sie können auch Little Endian verwenden, um zu berechnen und das gleiche Ergebnis zu erhalten.

Übrigens, wenn wir Zahlen in Code schreiben, denke ich, dass es wie ein Big-Endian-Format ist. 123456 oder 0x1Fdie wichtigsten Zahlen beginnen von links.

Nochmals, sobald wir ein binäres Format eines Werts auf das Papier schreiben, haben wir meiner Meinung nach bereits eine Endianess gewählt und sehen den Wert so, wie wir ihn aus dem Gedächtnis sehen.

Also zurück zur Frage, ein Schichtbetrieb << sollte gedacht werden als Verschiebung von LSB (niederwertigstes Byte) nach MSB (höchstwertiges Byte).

Dann wie für das Beispiel in der Frage:

numb=1025

Little-Endian

LSB 00000001 00000100 00000000 00000000 MSB

So << 10 wäre 10bit Umschalten von LSB auf MSB.


Vergleich u << 10 Operationen für das Little-Endian-Format Schritt für Schritt:

MSB                                        LSB
    00000000  00000000  00000100  00000001  numb(1025)
    00000000  00010000  00000100  00000000  << 10

LSB                                        MSB
    00000000  00000100  00010000  00000000 numb(1025) << 10, and put in a Little Endian Format

LSB                                        MSB
    00000001  00000100  00000000  00000000 numb(1205) in Little Endian format
    00000010  00001000  00000000  00000000 << 1 
    00000100  00010000  00000000  00000000 << 2 
    00001000  00100000  00000000  00000000 << 3 
    00010000  01000000  00000000  00000000 << 4
    00100000  10000000  00000000  00000000 << 5
    01000000  00000000  00000001  00000000 << 6
    10000000  00000000  00000010  00000000 << 7
    00000000  00000001  00000100  00000000 << 8
    00000000  00000010  00001000  00000000 << 9
    00000000  00000100  00010000  00000000 << 10 (check this final result!)

Wow! Ich bekomme das erwartete Ergebnis wie im OP beschrieben!

Die Probleme, dass das OP nicht das erwartete Ergebnis erzielt hat, sind:

  1. Es scheint, dass er nicht von LSB auf MSB umgeschaltet hat.

  2. Wenn Sie Bits im Little-Endian-Format verschieben, sollten Sie Folgendes erkennen (Gott sei Dank ist mir das klar):

LSB 10000000 00000000 MSB << 1 ist
LSB 00000000 00000001 MSB, nicht
LSB 01000000 00000000 MSB

Denn für jeden Einzelnen 8bitswir schreiben es eigentlich in a MSB 00000000 LSB Big-Endian-Format.

Es ist also wie

LSB[ (MSB 10000000 LSB) (MSB 00000000 LSB) ]MSB


Um zusammenzufassen:

  1. Obwohl gesagt wird, dass bitweise Operationen abstrahiert werden, blablablabla…, wenn wir bitweise Operationen von Hand berechnen, müssen wir immer noch wissen, welche Endianess wir verwenden, wenn wir das Binärformat auf das Papier schreiben. Außerdem müssen wir sicherstellen, dass alle Operatoren die gleiche Endianess verwenden.

  2. Der OP hat nicht das erwartete Ergebnis erzielt, weil er die Schaltung falsch gemacht hat.

Welcher Schiebebefehl die höherwertigen Bits zuerst herausschiebt, wird als Linksverschiebung betrachtet. Welche Verschiebungsanweisung die niederwertigen Bits zuerst herausschiebt, wird als Verschiebung nach rechts betrachtet. In diesem Sinne ist das Verhalten von >> und << zum unsigned Zahlen hängen nicht von Endianness ab.

Computer schreiben Zahlen nicht so auf wie wir. Der Wert verschiebt sich einfach. Wenn Sie darauf bestehen, es Byte für Byte zu betrachten (auch wenn der Computer es nicht so macht), könnten Sie sagen, dass auf einer Little-Endian-Maschine das erste Byte nach links verschoben wird und die überschüssigen Bits in das zweite Byte gehen. usw.

(Übrigens macht Little-Endian mehr Sinn, wenn Sie die Bytes vertikal statt horizontal schreiben, mit höheren Adressen oben. So werden Memory Map-Diagramme üblicherweise gezeichnet.)

1425270cookie-checkHängt die Bitverschiebung von der Endianness ab?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy