Co value & 0xff robi w Javie?

101

Mam następujący kod Java:

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

Wynik po wydrukowaniu to 254, ale nie mam pojęcia, jak działa ten kod. Jeśli &operator jest po prostu bitowy, dlaczego nie daje bajtu, a zamiast tego jest liczbą całkowitą?

dagronlund
źródło
Kopiuję kod do Eclipse. Ostrzega mnie „Niezgodność typów: nie można przekonwertować z wartości int na bajt”. Czy powinien zmienić się na wartość int = 0xfe;
Ben Cheng
1
@BenCheng powinno byćbyte value = (byte) 0xfe;
Bek

Odpowiedzi:

173

Ustawia resultwartość (bez znaku) wynikającą z umieszczenia 8 bitów valuew najniższych 8 bitach result.

Powodem, dla którego coś takiego jest konieczne, jest to, że bytejest to typ podpisany w Javie. Jeśli właśnie napisałeś:

int result = value;

wtedy resultotrzyma wartość ff ff ff fezamiast 00 00 00 fe. Kolejną subtelnością jest to, że &zdefiniowano, aby działał tylko na intwartościach 1 , więc dzieje się tak:

  1. valuejest promowany do int( ff ff ff fe).
  2. 0xffjest intliterałem ( 00 00 00 ff).
  3. &Stosuje się w celu uzyskania pożądanej wartości za result.

(Chodzi o to, że konwersja do intnastępuje przed zastosowaniem &operatora).

1 Cóż, niezupełnie. &Operator działa na longwartości, a także, jeśli którykolwiek z operandów jest long. Ale nie włączone byte. Zobacz specyfikację języka Java, sekcje 15.22.1 i 5.6.2 .

Ted Hopp
źródło
Co oznacza x w tym zapisie? x nie jest liczbą ani liczbą szesnastkową?
Callat
3
@KazRodgers - przedrostek 0x(lub 0X) informuje Javę, że następujący po nim literał liczby całkowitej powinien być interpretowany jako szesnastkowy (podstawa 16). Java obsługuje również czysty 0prefiks dla literałów ósemkowych i 0b(lub 0B) prefiks dla literałów binarnych. Więcej informacji na temat literałów całkowitych można znaleźć w specyfikacji języka Java .
Ted Hopp,
Dosłowny, który następuje? Czyli na przykład gdybym miał 0x3fa. 3fa to część tłumaczona na literalną liczbę, a 0x zwraca uwagę „to jest liczba szesnastkowa”? @TedHopp?
Callat
1
@KazRodgers - Dokładnie. Zwróć uwagę, że składnia 0xlub 0bsama w sobie (bez żadnych cyfr po niej) jest niedozwoloną składnią w Javie.
Ted Hopp,
1
@DmitryMinkovsky - Szesnastkowy wzorzec bitowy few 8-bitach, uzupełnienie do dwóch odpowiada wartości dziesiętnej -2. Aby zachować wartość, Integer.valueOf(byte)należałoby wygenerować ff ff ff fe(-2 w 32-bitach, uzupełnienie do dwóch), a nie 00 00 00 fe(wartość dziesiętna 254). Ta transformacja (z bytewartości fedo intwartości ff ff ff fe) jest znana jako rozszerzenie znaku i jest częścią specyfikacji języka Java. Celem programu value & 0xffjest cofnięcie rozszerzenia znaku (tj. Symulacja rozszerzenia zerowego, czego Java nie ma).
Ted Hopp,
57

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

Literał szesnastkowy 0xFF jest równą int (255). Java reprezentuje int jako 32 bity. Binarnie wygląda to tak:

00000000 00000000 00000000 11111111

Kiedy zrobisz trochę mądrze ORAZ z tą wartością (255) na dowolnej liczbie, zamaskuje (zrobi ZERO) wszystkie oprócz najniższych 8 bitów liczby (będzie tak jak jest).

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

I jest coś takiego jak%, ale nie naprawdę .

A dlaczego 0xff? to w ((potęga 2) - 1). Wszystkie ((potęga 2) - 1) (np. 7, 255 ...) będą zachowywać się jak operator%.

Następnie w
systemie binarnym 0 to wszystkie zera, a 255 wygląda następująco:

00000000 00000000 00000000 11111111

I tak wygląda -1

11111111 11111111 11111111 11111111

Kiedy wykonasz bitowe AND z 0xFF i dowolną wartość od 0 do 255, wynik jest dokładnie taki sam jak wartość. A jeśli jakakolwiek wartość wyższa niż 255 nadal będzie zawierała się w przedziale 0-255.

Jeśli jednak:

-1 & 0xFF

dostajesz

00000000 00000000 00000000 11111111, co NIE jest równe pierwotnej wartości -1 ( 11111111czyli 255 dziesiętnie).


Kilka dodatkowych manipulacji bitami: (Nie dotyczy pytania)

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

Sprawdź, czy konkretny bit jest ustawiony (1) czy nie (0)

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

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

Ustaw (1) określony bit

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

Ponownie ustaw (0) konkretny bit

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

XOR

Zwróć uwagę, że dwukrotne wykonanie operacji XOR da tę samą wartość.

byte toBeEncrypted = 0010 0110
byte salt          = 0100 1011

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

Jeszcze jedna logika z XOR to

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

Powyższe jest przydatne do zamiany dwóch zmiennych bez temp, jak poniżej

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

LUB

a ^= b ^= a ^= b;
Kanagavelu Sugumar
źródło
Zobacz także @ Bit manipulation stackoverflow.com/questions/13422259/…
Kanagavelu Sugumar
5

Pomaga zredukować wiele kodów. Jest czasami używany w wartościach RGB, które składają się z 8 bitów.

gdzie 0xff oznacza 24 (0) i 8 (1) podobne00000000 00000000 00000000 11111111

Skutecznie maskuje zmienną, więc pozostawia tylko wartość z ostatnich 8 bitów i ignoruje wszystkie pozostałe bity

Widać to najczęściej w przypadkach, takich jak próba przekształcenia wartości kolorów ze specjalnego formatu na standardowe wartości RGB (o długości 8 bitów).

Świetne wyjaśnienie Zobacz tutaj

AndroidGeek
źródło
0

W formacie 32 bit systemie szesnastkowym wartość 0xffoznacza 00000000000000000000000011111111, że jest 255(15*16^1+15*16^0)w układzie dziesiętnym. a operator bitowy & maskuje te same 8 skrajnych prawych bitów, jak w pierwszym operandzie.

manish kumar
źródło
czy możesz wyjaśnić trochę więcej.
ashishdhiman 2007