Value & 0xff ทำอะไรใน Java?


102

ฉันมีรหัส Java ต่อไปนี้:

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

ผลลัพธ์คือ 254 เมื่อพิมพ์ออกมา แต่ฉันไม่รู้ว่าโค้ดนี้ทำงานอย่างไร ถ้าตัว&ดำเนินการเป็นเพียงบิตทำไมจึงไม่ส่งผลให้เป็นไบต์และแทนที่จะเป็นจำนวนเต็ม?


ฉันคัดลอกโค้ดไปที่ Eclipse มันเตือนฉันว่า "ประเภทไม่ตรงกัน: ไม่สามารถแปลงจาก int เป็นไบต์" ควรเปลี่ยนเป็นค่า int = 0xfe;
Ben Cheng

1
@BenCheng ควรจะเป็นbyte value = (byte) 0xfe;
Bek

คำตอบ:


175

ตั้งค่า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ค่าเช่นกันถ้าตัวถูกดำเนินการเป็น a long. byteแต่ไม่ได้อยู่ใน ดูข้อมูลจำเพาะภาษา Java ส่วน15.22.1และ5.6.2


x หมายถึงอะไรในสัญกรณ์นั้น? x ไม่ใช่ตัวเลขหรือเลขฐานสิบหก?
Callat

3
@KazRodgers - คำนำหน้า0x(หรือ0X) บอก Java ว่าลิเทอรัลจำนวนเต็มที่ตามมาควรตีความเป็นเลขฐานสิบหก (ฐาน 16) Java ยังรองรับ0คำนำหน้าbare สำหรับลิเทอรัลฐานแปดและ a 0b(หรือ0B) คำนำหน้าสำหรับไบนารีลิเทอรัล ดูข้อกำหนดภาษา Javaสำหรับข้อมูลเพิ่มเติมในตัวอักษรจำนวนเต็ม
Ted Hopp

ตัวอักษรที่ตามมา? ตัวอย่างเช่นถ้าฉันมี 0x3fa 3fa คือส่วนที่ถูกแปลเป็นเลขตามตัวอักษรและ 0x สังเกตว่า "นี่คือเลขฐานสิบหก"? @TedHopp?
Callat

1
@KazRodgers - แน่นอน โปรดสังเกตว่า0xหรือ0bโดยตัวมันเอง (ไม่มีตัวเลขใด ๆ ต่อท้าย) เป็นไวยากรณ์ที่ผิดกฎหมายใน Java
Ted Hopp

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 ไม่มี)
Ted Hopp

59

จาก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

เมื่อคุณทำบิต AND เป็น 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

ข้างต้นมีประโยชน์ในการสลับสองตัวแปรโดยไม่มีอุณหภูมิเหมือนด้านล่าง

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

หรือ

a ^= b ^= a ^= b;

ยังได้ดู @ การจัดการบิตstackoverflow.com/questions/13422259/…
Kanagavelu Sugumar


5

ช่วยลดรหัสได้มาก บางครั้งใช้ในค่า RGB ซึ่งประกอบด้วย 8 บิต

โดยที่ 0xff หมายถึง 24 (0's) และ 8 (1's) like00000000 00000000 00000000 11111111

มันปิดบังตัวแปรได้อย่างมีประสิทธิภาพดังนั้นจึงเหลือเพียงค่าใน 8 บิตสุดท้ายและละเว้นส่วนที่เหลือทั้งหมด

พบได้บ่อยในกรณีเช่นเมื่อพยายามเปลี่ยนค่าสีจากรูปแบบพิเศษเป็นค่า RGB มาตรฐาน (ซึ่งมีความยาว 8 บิต)

คำอธิบายที่ยอดเยี่ยมดูที่นี่


0

ในระบบรูปแบบ 32 บิตค่าเลขฐานสิบหก0xffแสดง00000000000000000000000011111111ว่าเป็น255(15*16^1+15*16^0)ทศนิยม และตัวดำเนินการ bitwise & มาสก์ 8 บิตส่วนใหญ่เหมือนกันในตัวถูกดำเนินการแรก


คุณช่วยอธิบายเพิ่มเติมได้ไหม
ashishdhiman2007
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.