Що робить value & 0xff у Java?


98

У мене є такий код Java:

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

Результат - 254 при друку, але я не уявляю, як працює цей код. Якщо &оператор просто бітовий, то чому це не призводить до байту, а замість цього цілого числа?


Я копіюю код у Eclipse. Це попереджає мене "Невідповідність типу: неможливо перетворити з int на байт". Якщо воно зміниться на int значення = 0xfe;
Бен Ченг,

1
@BenCheng має бутиbyte value = (byte) 0xfe;
Бек

Відповіді:


171

Він встановлює resultзначення (без знака), що виникає в результаті введення 8 бітів valueв найнижчі 8 бітів result.

Причиною чогось подібного є те, що byteце тип підпису в Java. Якщо ви щойно написали:

int result = value;

тоді resultзакінчиться значенням ff ff ff feзамість 00 00 00 fe. Подальша тонкощі полягає в &тому, що визначено функціонувати лише зі intзначеннями 1 , тож відбувається:

  1. valueпідвищується до int( ff ff ff fe).
  2. 0xffє intлітералом ( 00 00 00 ff).
  3. &Наноситься з отриманням бажаного значення для result.

(Справа в тому, що перетворення в intвідбувається до того, &як застосовується оператор.)

1 Ну, не зовсім. &Оператор працює на longзначеннях , а також, якщо один з операндів є long. Але не на byte. Див. Специфікацію мови Java, розділи 15.22.1 та 5.6.2 .


Що означає х у цьому позначенні? x не є числом або шістнадцятковим числом?
Каллат

3
@KazRodgers - Префікс 0x(або 0X) повідомляє Java, що наступний цілочисельний літерал слід інтерпретувати як шістнадцятковий (основа 16). Java також підтримує голий 0префікс для восьмеричних літералів та 0b(або 0B) префікс для двійкових літералів. Докладніше про цілочисельні літерали див. У специфікації мови Java .
Тед Хопп,

Буквал, який слідує? Так, наприклад, якби я мав 0x3fa. 3fa - це частина, що перекладається в буквальне число, а 0x відзначає "це шістнадцяткове число"? @TedHopp?
Каллат

1
@KazRodgers - Саме так. Зверніть увагу , що 0xі 0bсам по собі (без будь - яких цифр , наступних) є незаконним синтаксис Java.
Тед Хопп,

1
@DmitryMinkovsky - Шістнадцятковий бітовий шаблон feу 8-бітному додатку двох відповідає десятковому значенню -2. Щоб зберегти значення, Integer.valueOf(byte)потрібно було б створити ff ff ff fe(-2 у 32-розрядному, доповнення двох), а не 00 00 00 fe(десяткове значення 254). Це перетворення (зі byteзначення feу intзначення ff ff ff fe) відоме як розширення знаку та є частиною специфікації мови Java. Метою value & 0xffє скасування розширення знаку (тобто для імітації нульового розширення, чогось у Java немає).
Тед Хопп,

57

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

Шістнадцятковий літерал 0xFF дорівнює int (255). Java представляє int як 32 біти. Це виглядає так у бінарному файлі:

00000000 00000000 00000000 11111111

Коли ви зробите трохи мудро І з цим значенням (255) для будь-якого числа, воно буде маскувати (робити НУЛІВ) всі, крім найнижчих 8 бітів числа (буде як є).

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

& - це щось на зразок%, але насправді не так .

А чому 0xff? це в ((потужність 2) - 1). Усі ((потужність 2) - 1) (наприклад, 7, 255 ...) будуть поводитися приблизно так, як% оператор.

Тоді
в довічним, 0, всі нулі, і 255 виглядає наступним чином :

00000000 00000000 00000000 11111111

А -1 виглядає так

11111111 11111111 11111111 11111111

Коли ви робите побітове І 0xFF і будь-яке значення від 0 до 255, результат точно відповідає значенню. І якщо будь-яке значення вище 255, результат все одно буде в межах 0-255.

Однак якщо ви це зробите:

-1 & 0xFF

Ви отримуєте

00000000 00000000 00000000 11111111, яке НЕ дорівнює вихідному значенню -1 ( 11111111дорівнює 255 в десяткових цифрах).


Ще декілька бітових маніпуляцій: (Не пов'язано з питанням)

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

Тоді перевірте, чи встановлено будь-який конкретний біт (1) чи ні (0)

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

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

Встановити (1) певний біт

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

Повторно встановити (0) певний біт

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

XOR

Тільки зауважте, що якщо ви виконуєте операцію XOR двічі, це дасть одне і те ж значення.

byte toBeEncrypted = 0010 0110
byte salt          = 0100 1011

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

Ще однією логікою XOR є

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

Вищевказане корисне для обміну двома змінними без temp, як показано нижче

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

АБО

a ^= b ^= a ^= b;

Крім того, є вид @ маніпуляції Bit stackoverflow.com/questions/13422259 / ...
Kanagavelu Sugumar


4

Це допомагає зменшити багато кодів. Він іноді використовується у значеннях RGB, які складаються з 8 бітів.

де 0xff означає 24 (0) і 8 (1) подібних00000000 00000000 00000000 11111111

Він ефективно маскує змінну, тому залишає лише значення в останніх 8 бітах, а всі інші біти ігнорує

Це спостерігається найбільше у таких випадках, як при спробі перетворити значення кольору зі спеціального формату в стандартні значення RGB (довжина яких становить 8 біт).

Чудове пояснення Дивіться тут


0

У 32 бітному форматі системи шістнадцяткове значення 0xffпредставляє 00000000000000000000000011111111тобто 255(15*16^1+15*16^0)в десяткової системі . і побітове & оператор маскує ті самі 8 більшості правих бітів, що і в першому операнді.


Ви можете пояснити трохи більше.
ashishdhiman2007
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.