wake-up-neo.com

Was macht AND 0xFF?

Im folgenden Code:

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

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

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

Und das scheint auch gut zu funktionieren?

35
Muis

Wenn Sie eine Ganzzahl mit 0xFF eingeben, bleibt nur das niedrigstwertige Byte übrig. Um zum Beispiel das erste Byte in einem short s zu erhalten, können Sie s & 0xFF schreiben. Dies wird typischerweise als "Maskierung" bezeichnet. Wenn byte1 entweder ein einzelner Byte-Typ ist (wie uint8_t) oder bereits kleiner als 256 ist (und als Ergebnis alle Nullen außer dem niedrigstwertigen Byte sind), müssen die höheren Bits nicht ausgeblendet werden, da sie bereits null sind.

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

33
John Colanduoni

wenn byte1 ein ganzzahliger 8-Bit-Typ ist, ist dies sinnlos - wenn es mehr als 8 Bit ist, werden im Wesentlichen die letzten 8 Bits des Werts angezeigt:

    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
24
D Stanley

Die Gefahr des zweiten Ausdrucks besteht, wenn der Typ von byte1char ist. In diesem Fall kann es für einige Implementierungen signed char geben, was bei der Auswertung zur Erweiterung des Vorzeichens 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 unter Solaris SPARC 64-Bit ausprobiert und das Ergebnis ist dasselbe, wobei byte1 und byte2 als char deklariert sind.

TL; DR

Die Maskierung dient dazu, eine implizite Vorzeichenerweiterung zu vermeiden.

EDIT: Ich habe geprüft, es ist dasselbe Verhalten in C++.

19

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

Also ist byte1 dasselbe wie byte1 & 0xFF

Sagen Sie, 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, so erhalten Sie bitweise AND mit 0xFF mit dem niedrigstwertigen Byte (8 Bits) von Byte1. 

6

Der byte1 & 0xff stellt sicher, dass nur die 8 niedrigstwertigen Bits von byte1 nicht Null sein können.

wenn byte1 bereits ein vorzeichenloser Typ mit nur 8 Bits ist (in einigen Fällen char oder in den meisten Fällen unsigned char), hat dies keinen Unterschied/ist völlig unnötig.

Wenn byte1 ein Typ ist, der vorzeichenbehaftet ist oder mehr als 8 Bits enthält (z. B. short, int, long) und eines der Bits mit Ausnahme der 8 niedrigstwertigen Bits gesetzt ist, besteht ein Unterschied (dh, diese werden auf Null gesetzt.) obere Bits vor oring mit der anderen Variablen, so dass dieser Operand der or nur die 8 niederwertigsten Bits des Ergebnisses beeinflusst.

3
Jerry Coffin

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

1
thumbmunkeys

& 0xFF alleine stellt nur sicher, dass der Rest ignoriert wird, wenn Bytes länger als 8 Bit sind (vom Sprachstandard zugelassen).

Und das scheint auch gut zu funktionieren?

Wenn das Ergebnis größer als SHRT_MAX ist, erhalten Sie ein undefiniertes Verhalten. In dieser Hinsicht werden beide gleichermaßen schlecht arbeiten.

0
Alexey Frunze