Was macht UND 0xFF?

Lesezeit: 5 Minuten

Im folgenden Code:

short = ((byte2 << 8) | (byte1 & 0xFF))

Was ist der Zweck von &0xFF? Weil andere manchmal sehe ich es geschrieben als:

short = ((byte2 << 8) | byte1)

Und das scheint auch gut zu funktionieren?

  • Ist Byte1 vom Typ uint8_t?

    – Shahbaz

    5. Februar 2013 um 17:17 Uhr

  • Dann denke ich, es ist nur “nur um sicher zu gehen”. Wahrscheinlich hat derjenige, der es geschrieben hat, versucht, auf Nummer sicher zu gehen, falls jemand die Art von ändert byte1was ziemlich wahrscheinlich scheint, weil byte2 ist schon nicht 8-bit (sonst byte2 << 8 ist 0)

    – Shahbaz

    5. Februar 2013 um 17:33 Uhr


  • Es tut uns leid, byte2 << 8 funktioniert auch wenn byte2 ist ein 8-Bit-Typ. Standardmäßig funktionieren Ausdrücke immer als int. Der Compiler sieht implizit den Ausdruck als ((int)byte2) << ((int)8)

    – Patrick Schlüter

    5. Februar 2013 um 17:40 Uhr

  • Übrigens, short ist ein reserviertes Wort und kann nicht als Variablenname verwendet werden.

    – Patrick Schlüter

    5. Februar 2013 um 17:46 Uhr

wenn byte1 ein 8-Bit-Integer-Typ ist, dann ist es sinnlos – wenn es mehr als 8 Bit sind, erhalten Sie im Wesentlichen die letzten 8 Bit des Werts:

    0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
 &  0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
    -------------------------------
    0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1

Benutzeravatar von John Colanduoni
John Colanduoni

Anding einer Ganzzahl mit 0xFF lässt nur das niedrigstwertige Byte übrig. Um beispielsweise das erste Byte in a zu erhalten short sDu kannst schreiben s & 0xFF. Dies wird typischerweise als “Maskierung” bezeichnet. Wenn byte1 ist entweder ein Single-Byte-Typ (wie uint8_t) oder bereits kleiner als 256 ist (und daher bis auf das niedrigstwertige Byte alle Nullen sind), müssen die höherwertigen Bits nicht ausgeblendet werden, da sie bereits Null sind.

Sehen TristopiePatrick Schlüters Antwort unten, wenn Sie möglicherweise mit signierten Typen arbeiten. Bei bitweisen Operationen empfehle ich, nur mit vorzeichenlosen Typen zu arbeiten.

Benutzeravatar von Patrick Schlüter
Patrick Schlüter

Die Gefahr des zweiten Ausdrucks kommt, wenn der Typ von byte1 ist char. In diesem Fall können einige Implementierungen es haben signed charwas bei der Auswertung zu einer Vorzeichenerweiterung führt.

signed char byte1 = 0x80;
signed char byte2 = 0x10;

unsigned short value1 = ((byte2 << 8) | (byte1 & 0xFF));
unsigned short value2 = ((byte2 << 8) | byte1);

printf("value1=%hu %hx\n", value1, value1);
printf("value2=%hu %hx\n", value2, value2);

wird drucken

value1=4224 1080     right
value2=65408 ff80    wrong!!

Ich habe es auf gcc v3.4.6 auf Solaris SPARC 64 Bit versucht und das Ergebnis ist das gleiche mit byte1 und byte2 deklariert als char.

TL;DR

Die Maskierung dient dazu, eine implizite Zeichenerweiterung zu vermeiden.

BEARBEITEN: Ich habe es überprüft, es ist das gleiche Verhalten in C++.

EDIT2: Wie angeforderte Erklärung der Zeichenerweiterung. Die Vorzeichenerweiterung ist eine Folge davon, wie C Ausdrücke auswertet. Es gibt eine Regel in C, die Promotion-Regel genannt wird. C wandelt implizit alle kleinen Typen in um int bevor Sie die Auswertung vornehmen. Mal sehen, was mit unserem Ausdruck passiert:

unsigned short value2 = ((byte2 << 8) | byte1);

byte1 ist eine Variable, die das Bitmuster 0xFF enthält. Wenn char ist unsigned dieser Wert wird als 255 interpretiert, falls dies der Fall ist signed es ist -128. Bei der Berechnung erweitert C den Wert auf an int Größe (im Allgemeinen 16 oder 32 Bit). Das heißt, wenn die Variable ist unsigned und wir behalten den Wert 255, das Bitmuster dieses Werts bei int wird 0x000000FF sein. Wenn ja signed Wir wollen den Wert -128, dessen Bitmuster 0xFFFFFFFF ist. Das Zeichen wurde auf die Größe des für die Berechnung verwendeten Temporärs erweitert. Und somit führt das Oring des Temporärs zu einem falschen Ergebnis.

Bei der x86-Assemblierung erfolgt dies mit der movsx Anweisung (movzx für die Nullausdehnung). Andere CPUs hatten dafür andere Anweisungen (6809 hatte SEX).

  • +1 für die Warnung, aber ich verstehe nicht warum oder was “Sign Extension” ist, können Sie mit einer einfachen Erklärung bearbeiten?

    – doc_id

    14. Januar 2021 um 17:08 Uhr

  • Hier eine kurze Erklärung. Sie sollten den Link nachschlagen, den ich dort gesetzt habe, um mehr über die Beförderungsregeln von C zu erfahren, da es ein sehr wichtiger Punkt ist, dass Leute, sogar erfahrene Programmierer, sich in Bezug auf die Sprache irren.

    – Patrick Schlüter

    15. Januar 2021 um 14:20 Uhr

Benutzeravatar von sr01853
sr01853

Angenommen Ihr byte1 ist ein Byte (8 Bits). Wenn Sie ein bitweises UND eines Bytes mit 0xFF ausführen, erhalten Sie dasselbe Byte.

So byte1 ist das gleiche wie byte1 & 0xFF

Sagen byte1 ist 01001101 dann byte1 & 0xFF = 01001101 & 11111111 = 01001101 = byte1

Wenn byte1 von einem anderen Typ ist, sagen wir eine ganze Zahl von 4 Bytes, hinterlässt bitweises AND mit 0xFF das niederwertigste Byte (8 Bits) von Byte1.

Benutzeravatar von Jerry Coffin
Jerry Sarg

Das byte1 & 0xff sorgt dafür, dass nur die 8 niederwertigsten Bits aus byte1 kann ungleich Null sein.

wenn byte1 ist bereits ein vorzeichenloser Typ, der nur 8 Bit hat (z. B. char in manchen Fällen bzw unsigned char in den meisten Fällen) macht es keinen Unterschied/ist völlig unnötig.

Wenn byte1 ist ein Typ, der signiert ist oder mehr als 8 Bit hat (z. B. short, int, long) und eines der Bits außer den 8 niederwertigsten gesetzt ist, dann wird es einen Unterschied geben (dh es werden diese oberen Bits vorher auf Null gesetzt oring mit der anderen Variablen, also dieser Operand der or beeinflusst nur die 8 niederwertigsten Bits des Ergebnisses).

  • Nein, siehe meine Antwort oben. Wenn die Art von byte1 ist char oder signed char es ist absolut notwendig.

    – Patrick Schlüter

    5. Februar 2013 um 17:54 Uhr

Benutzeravatar von thumbmunkeys
Daumenmücken

es löscht alle Bits, die nicht im ersten Byte sind

  • Nein, siehe meine Antwort oben. Wenn die Art von byte1 ist char oder signed char es ist absolut notwendig.

    – Patrick Schlüter

    5. Februar 2013 um 17:54 Uhr

Benutzeravatar von Alexey Frunze
Alexej Frunze

& 0xFF allein sorgt nur dafür, dass Bytes, die länger als 8 Bit sind (vom Sprachstandard erlaubt), den Rest ignorieren.

Und das scheint auch gut zu funktionieren?

Wenn das Ergebnis größer als endet SHRT_MAX, erhalten Sie undefiniertes Verhalten. Insofern werden beide gleich schlecht funktionieren.

1411280cookie-checkWas macht UND 0xFF?

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

Privacy policy