Bit Masking คืออะไร


191

ฉันค่อนข้างใหม่สำหรับการเขียนโปรแกรม C และฉันพบการปิดบังเล็กน้อย บางคนสามารถอธิบายแนวคิดและหน้าที่ทั่วไปของการปิดบังบิตให้ฉันได้หรือไม่ ตัวอย่างชื่นชมมาก


1
คุณเข้าใจผู้ประกอบการระดับบิตเช่น & | หรือไม่ ^ etc และบูลีนลอจิกทั่วไป? คำอธิบายใด ๆ ของการดำเนินงานของหน้ากากจะต้องมีสิ่งนี้
Paul R

1
ใช่ฉันมีความเข้าใจในตัวดำเนินการระดับบิตและตรรกะบูลีน
Mr.Z

2
ฉันรู้ว่าลิงก์ไม่ควรโพสต์ แต่คำอธิบายวิกิพีเดียดีมาก: en.wikipedia.org/wiki/Mask_(computing)
pevik

2
@pevik โอเคที่จะโพสต์ลิงก์ แต่มีคำอธิบายบางอย่างเพื่อให้ถ้าลิงก์ตายสักวันโพสต์จะยังคงสามารถตอบสนองวัตถุประสงค์ในการตอบได้ ลิงก์ไม่ควรใช้เพื่อจุดประสงค์ในการโปรโมตเท่านั้น
เด็กซ์เตอร์

คำตอบ:


245

หน้ากากจะกำหนดว่าคุณต้องการเก็บบิตใดและบิตใดที่คุณต้องการล้าง

การปิดบังคือการกระทำที่ใช้มาส์กกับค่า นี่คือความสำเร็จโดยทำ:

  • Bitwise ANDing เพื่อแยกชุดย่อยของบิตในค่า
  • Bitwise ORing เพื่อตั้งค่าเซตย่อยของบิตในค่า
  • Bitwise XORing เพื่อสลับชุดย่อยของบิตในค่า

ด้านล่างเป็นตัวอย่างของการแยกเซ็ตย่อยของบิตในค่า:

Mask:   00001111b
Value:  01010101b

การนำรูปแบบไปใช้กับค่าหมายความว่าเราต้องการล้างบิตแรก (สูงกว่า) 4 บิตและเก็บบิตสุดท้าย (ล่าง) 4 บิต ดังนั้นเราจึงแยก 4 บิตที่ต่ำกว่า ผลลัพธ์คือ:

Mask:   00001111b
Value:  01010101b
Result: 00000101b

กาวถูกนำมาใช้โดยใช้ AND ดังนั้นใน C เราได้รับ

uint8_t stuff(...) {
  uint8_t mask = 0x0f;   // 00001111b
  uint8_t value = 0x55;  // 01010101b
  return mask & value;
}

นี่เป็นกรณีการใช้งานที่ค่อนข้างทั่วไป: การแยกแต่ละไบต์จากคำที่ใหญ่ เรากำหนดบิตการเรียงลำดับสูงในคำว่าเป็นไบต์แรก เราใช้ตัวดำเนินการสองตัวสำหรับสิ่งนี้&และ>>(เลื่อนไปทางขวา) นี่คือวิธีที่เราสามารถแยกสี่ไบต์จากจำนวนเต็ม 32 บิต:

void more_stuff(uint32_t value) {             // Example value: 0x01020304
    uint32_t byte1 = (value >> 24);           // 0x01020304 >> 24 is 0x01 so
                                              // no masking is necessary
    uint32_t byte2 = (value >> 16) & 0xff;    // 0x01020304 >> 16 is 0x0102 so
                                              // we must mask to get 0x02
    uint32_t byte3 = (value >> 8)  & 0xff;    // 0x01020304 >> 8 is 0x010203 so
                                              // we must mask to get 0x03
    uint32_t byte4 = value & 0xff;            // here we only mask, no shifting
                                              // is necessary
    ...
}

โปรดสังเกตว่าคุณสามารถสลับคำสั่งของผู้ให้บริการด้านบนได้คุณสามารถทำหน้ากากก่อนแล้วจึงเปลี่ยน ผลลัพธ์เหมือนกัน แต่ตอนนี้คุณต้องใช้มาสก์ที่แตกต่างกัน:

uint32_t byte3 = (value & 0xff00) >> 8;

5
คำตอบที่ดี แต่การปิดบังสามารถใช้สำหรับการตั้งค่าหรือสลับบิตเฉพาะกับการดำเนินการ OR หรือ XOR และรูปแบบที่เหมาะสม
Paul R

@ user239558 ขอบคุณสำหรับตัวอย่างและไวยากรณ์ที่เหมาะสม @ Paul R. ฉันจะพูดเพียง mask และค่าในตัวอย่างที่มีให้โดยผู้ใช้ 239558
Mr.Z

@ Mr.Z: ใน C, C ++ และภาษาที่เกี่ยวข้องกับที่คุณทำคุณบิตและ&ผู้ประกอบการซึ่งเขียนเป็น
Paul R

@ Mr.Z ตัวอย่างเช่น: ชัดเจนหนึ่งไบต์ของ uint32_t #define MASK 0x000000FF .... my_uint32_t &= ~MASKโดยกำบังเนื้อหาออกไป:
Lundin

bที่แท้จริงเพื่อระบุไบนารีไม่สนับสนุนคอมไพเลอร์ทั้งหมดถูกต้องหรือไม่
Ungeheuer

76

การปิดบังหมายถึงการเก็บ / เปลี่ยนแปลง / ลบส่วนที่ต้องการของข้อมูล ให้ดูการดำเนินการปิดบังภาพ การดำเนินการปิดบังเช่นนี้เป็นการลบสิ่งที่ไม่ใช่ผิวหนังออก

ป้อนคำอธิบายรูปภาพที่นี่

เรากำลังดำเนินการและดำเนินการในตัวอย่างนี้ นอกจากนี้ยังมีการหลอกลวงอื่น ๆ operators- หรือ , แฮคเกอร์


Bit-Maskingหมายถึงรูปแบบการทับซ้อนทับบิต นี่คือการหลอกลวงเล็กน้อยกับAND -

     1 1 1 0 1 1 0 1   [input]
(&)  0 0 1 1 1 1 0 0    [mask]
------------------------------
     0 0 1 0 1 1 0 0  [output]

ดังนั้นเหลือเพียง 4 บิตกลาง (เนื่องจากบิตเหล่านี้อยู่1ในรูปแบบนี้) จึงยังคงอยู่

ให้ดูด้วยXOR -

     1 1 1 0 1 1 0 1   [input]
(^)  0 0 1 1 1 1 0 0    [mask]
------------------------------
     1 1 0 1 0 0 0 1  [output]

ตอนกลาง 4 บิตจะพลิก ( 1กลายเป็น0, 0กลายเป็น1)


ดังนั้นการใช้บิตมาสก์เราสามารถเข้าถึงแต่ละบิต [ ตัวอย่าง ] บางครั้งเทคนิคนี้อาจใช้สำหรับการปรับปรุงประสิทธิภาพ ใช้เวลานี้เป็นตัวอย่าง -

bool isOdd(int i) {
    return i%2;
}

ฟังก์ชั่นนี้จะบอกว่าเป็นจำนวนเต็มคี่ / คู่ เราสามารถบรรลุผลลัพธ์เดียวกันด้วยประสิทธิภาพมากขึ้นโดยใช้บิตมาสก์

bool isOdd(int i) {
    return i&1;
}

คำอธิบายสั้น ๆ : ถ้าบิตที่มีนัยสำคัญน้อยที่สุดของเลขฐานสอง1มันจะเป็นเลขคี่ เพราะ0มันจะเป็นอย่างนั้น ดังนั้นด้วยการทำและกับ1เรากำลังลบบิตอื่น ๆ ทั้งหมดยกเว้นบิตที่สำคัญน้อยที่สุดเช่น:

     55  ->  0 0 1 1 0 1 1 1   [input]
(&)   1  ->  0 0 0 0 0 0 0 1    [mask]
---------------------------------------
      1  <-  0 0 0 0 0 0 0 1  [output]

1
นอกจากนี้ในการแปลงจำนวนเต็มเป็นเลขคี่ หากเป็นเลขคู่: i = i | 1 สิ่งนี้มีประโยชน์เมื่อเราพยายามสร้างลำดับเช่น 1, 3, 5, ... , 2, 4, 6, ...
Harshit Sharma

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