Was macht value & 0xff in Java?

98

Ich habe den folgenden Java-Code:

byte value = 0xfe; // corresponds to -2 (signed) and 254 (unsigned)
int result = value & 0xff;

Das Ergebnis ist 254 beim Drucken, aber ich habe keine Ahnung, wie dieser Code funktioniert. Wenn der &Operator einfach bitweise ist, warum führt er dann nicht zu einem Byte und stattdessen zu einer Ganzzahl?

Dagronlund
quelle
Ich kopiere den Code nach Eclipse. Es warnt mich "Typ stimmt nicht überein: Konvertiert nicht von int in Byte". Sollte sich der Wert auf int = 0xfe ändern;
Ben Cheng
@ BenCheng sollte seinbyte value = (byte) 0xfe;
Bek vor

Antworten:

171

Es wird resultauf den (vorzeichenlosen) Wert gesetzt, der sich aus dem Setzen der 8 Bits valuein die niedrigsten 8 Bits von ergibt result.

Der Grund, warum so etwas notwendig ist, byteist, dass es sich um einen signierten Typ in Java handelt. Wenn Sie gerade geschrieben haben:

int result = value;

dann resultwürde mit dem Wert ff ff ff festatt enden 00 00 00 fe. Eine weitere Feinheit ist, dass das &so definiert ist, dass es nur mit den intWerten 1 arbeitet. Was also passiert, ist:

  1. valuewird zu einem int( ff ff ff fe) befördert.
  2. 0xffist ein intLiteral ( 00 00 00 ff).
  3. Das &wird angewendet, um den gewünschten Wert für zu erhalten result.

(Der Punkt ist, dass die Konvertierung in interfolgt, bevor der &Operator angewendet wird.)

1 Nun, nicht ganz. Der &Operator arbeitet auch mit longWerten, wenn einer der Operanden a ist long. Aber nicht weiter byte. Siehe die Java-Sprachspezifikation, Abschnitte 15.22.1 und 5.6.2 .

Ted Hopp
quelle
Was bedeutet das x in dieser Notation? x ist keine Zahl oder Hexadezimalzahl?
Callat
3
@KazRodgers - Das Präfix 0x(oder 0X) teilt Java mit, dass das folgende Ganzzahlliteral als hexadezimal interpretiert werden soll (Basis 16). Java unterstützt auch ein nacktes 0Präfix für Oktalliterale und ein 0b(oder 0B) Präfix für Binärliterale. Weitere Informationen zu Ganzzahlliteralen finden Sie in der Java-Sprachspezifikation .
Ted Hopp
Das folgende Wort? Also zum Beispiel wenn ich 0x3fa hätte. Die 3fa ist der Teil, der in eine Literalzahl übersetzt wird, und 0x stellt fest, dass "dies eine Hexadezimalzahl ist"? @ TedHopp?
Callat
1
@ KazRodgers - Genau. Beachten Sie, dass 0xoder 0bfür sich (ohne Ziffern) in Java eine unzulässige Syntax ist.
Ted Hopp
1
@DmitryMinkovsky - Das Hex-Bitmuster feim 8-Bit-Zweierkomplement entspricht dem Dezimalwert −2. Um den Wert beizubehalten, Integer.valueOf(byte)müsste ff ff ff fe(−2 in 32-Bit, Zweierkomplement) erzeugt werden, nicht 00 00 00 fe(Dezimalwert 254). Diese Umwandlung (von einem byteWert fein einen intWert ff ff ff fe) wird als Vorzeichenerweiterung bezeichnet und ist Teil der Java-Sprachspezifikation. Der Zweck von value & 0xffbesteht darin, die Vorzeichenerweiterung rückgängig zu machen (dh eine Nullerweiterung zu simulieren, etwas, das Java nicht hat).
Ted Hopp
57

Von http://www.coderanch.com/t/236675/java-programmer-SCJP/certification/xff

Das Hex-Literal 0xFF ist gleich int (255). Java repräsentiert int als 32 Bit. In Binärform sieht es so aus:

00000000 00000000 00000000 11111111

Wenn Sie ein bisschen weise UND mit diesem Wert (255) für eine beliebige Zahl ausführen, werden alle bis auf die niedrigsten 8 Bits der Zahl maskiert (NULL gemacht) (wie sie sind).

... 01100100 00000101 & ...00000000 11111111 = 00000000 00000101

& ist so etwas wie%, aber nicht wirklich .

Und warum 0xff? dies in ((Potenz von 2) - 1). Alle ((Potenz von 2) - 1) (z. B. 7, 255 ...) verhalten sich so etwas wie% Operator.

Dann ist
in binär 0 alle Nullen und 255 sieht folgendermaßen aus:

00000000 00000000 00000000 11111111

Und -1 sieht so aus

11111111 11111111 11111111 11111111

Wenn Sie ein bitweises UND von 0xFF und einen Wert von 0 bis 255 ausführen, entspricht das Ergebnis genau dem Wert. Und wenn ein Wert höher als 255 ist, liegt das Ergebnis immer noch zwischen 0 und 255.

Wenn Sie jedoch Folgendes tun:

-1 & 0xFF

du erhältst

00000000 00000000 00000000 11111111, was NICHT dem ursprünglichen Wert von -1 entspricht ( 11111111ist 255 in Dezimalzahl).


Noch ein paar Bitmanipulationen: (Nicht im Zusammenhang mit der Frage)

X >> 1 = X/2
X << 1 = 2X

Überprüfen Sie, ob ein bestimmtes Bit gesetzt ist (1) oder nicht (0)

 int thirdBitTobeChecked =   1 << 2   (...0000100)
 int onWhichThisHasTobeTested = 5     (.......101)

 int isBitSet = onWhichThisHasTobeTested  & thirdBitTobeChecked;
 if(isBitSet > 0) {
  //Third Bit is set to 1 
 } 

Setze (1) ein bestimmtes Bit

 int thirdBitTobeSet =   1 << 2    (...0000100)
 int onWhichThisHasTobeSet = 2     (.......010)
 onWhichThisHasTobeSet |= thirdBitTobeSet;

Setzen Sie ein bestimmtes Bit zurück (0)

int thirdBitTobeReSet =   ~(1 << 2)  ; //(...1111011)
int onWhichThisHasTobeReSet = 6      ;//(.....000110)
onWhichThisHasTobeReSet &= thirdBitTobeReSet;

XOR

Beachten Sie nur, dass bei zweimaliger XOR-Operation derselbe Wert angezeigt wird.

byte toBeEncrypted = 0010 0110
byte salt          = 0100 1011

byte encryptedVal  =  toBeEncrypted ^ salt == 0110 1101
byte decryptedVal  =  encryptedVal  ^ salt == 0010 0110 == toBeEncrypted :)

Eine weitere Logik mit XOR ist

if     A (XOR) B == C (salt)
then   C (XOR) B == A
       C (XOR) A == B

Das Obige ist nützlich, um zwei Variablen ohne Temperatur wie unten zu tauschen

a = a ^ b; b = a ^ b; a = a ^ b;

ODER

a ^= b ^= a ^= b;
Kanagavelu Sugumar
quelle
Schauen Sie auch @ Bit Manipulation stackoverflow.com/questions/13422259/…
Kanagavelu Sugumar
4

Es hilft, viele Codes zu reduzieren. Es wird gelegentlich in RGB-Werten verwendet, die aus 8 Bit bestehen.

wobei 0xff 24 (0) und 8 (1) wie bedeutet00000000 00000000 00000000 11111111

Die Variable wird effektiv maskiert, sodass nur der Wert in den letzten 8 Bits übrig bleibt, und alle übrigen Bits werden ignoriert

Dies tritt am häufigsten in Fällen auf, in denen versucht wird, Farbwerte von einem speziellen Format in Standard-RGB-Werte (die 8 Bit lang sind) umzuwandeln.

Tolle Erklärung Siehe hier

Zar E Ahmer
quelle
0

In 32 - Bit - Format System der hexadezimale Wert 0xffrepräsentiert 00000000000000000000000011111111das ist 255(15*16^1+15*16^0)in dezimal. und der bitweise & Operator maskiert die gleichen 8 Bits ganz rechts wie im ersten Operanden.

manish kumar
quelle
Kannst du etwas mehr erklären?
ashishdhiman2007