กลับไปหน้าบทความ

อ่าน 6 นาที

บิตฟิลด์

ฟิลด์ บิต เป็น โครงสร้างข้อมูล ที่แมปกับ บิต ที่อยู่ติดกันตั้งแต่หนึ่งบิตขึ้นไปซึ่งได้รับการจัดสรรไว้เพื่อวัตถุประสงค์เฉพาะ...

บิตฟิลด์

ฟิลด์บิตเป็นโครงสร้างข้อมูล ที่แมปกับ บิตที่อยู่ติดกันตั้งแต่หนึ่งบิตขึ้นไปซึ่งได้รับการจัดสรรไว้เพื่อวัตถุประสงค์เฉพาะ เพื่อให้สามารถตั้งค่าหรือตรวจสอบบิตเดี่ยวหรือกลุ่มบิตใดๆ ภายในโครงสร้างได้[ 1 ] [ 2 ]ฟิลด์บิตมักใช้เพื่อแสดงประเภทจำนวนเต็มที่มีความกว้างบิตคงที่ที่ทราบ เช่นบูลีนบิต เดียว

ความหมายของบิตแต่ละบิตภายในฟิลด์จะถูกกำหนดโดยโปรแกรมเมอร์ ตัวอย่างเช่น บิตแรกในฟิลด์บิต (ซึ่งอยู่ที่แอดเดรสฐาน ของฟิลด์ ) บางครั้งถูกใช้เพื่อกำหนดสถานะของแอตทริบิวต์เฉพาะที่เกี่ยวข้องกับฟิลด์บิต[ 3 ]

ภายในCPUและอุปกรณ์ลอจิกอื่นๆ ชุดของฟิลด์บิตที่เรียกว่าแฟล็กมักใช้เพื่อควบคุมหรือระบุผลลัพธ์ของการดำเนินการเฉพาะ[ 4 ]โปรเซสเซอร์มีรีจิสเตอร์สถานะที่ประกอบด้วยแฟล็ก ตัวอย่างเช่น หากผลลัพธ์ของการบวกไม่สามารถแสดงในปลายทางได้ จะเกิด การโอเวอร์โฟลว์ทางคณิตศาสตร์แฟล็กสามารถใช้เพื่อตัดสินใจการดำเนินการที่ตามมา เช่นคำสั่งกระโดด แบบมีเงื่อนไข ตัวอย่างเช่นคำสั่ง (Jump if Equal) ในภาษาแอสเซมบลี x86จะส่งผลให้เกิดการกระโดดหากแฟล็ก Z (ศูนย์)ถูกตั้งค่าโดยการดำเนินการก่อนหน้าบางอย่าง JE...

ฟิลด์บิตแตกต่างจากอาร์เรย์บิตตรงที่อาร์เรย์บิตใช้สำหรับจัดเก็บชุดบิตขนาดใหญ่ที่มีดัชนีเป็นจำนวนเต็ม และมักจะกว้างกว่าชนิดข้อมูลจำนวนเต็มใดๆ ที่ภาษานั้นรองรับ ในทางกลับกัน ฟิลด์บิตโดยทั่วไปจะพอดีกับคำเครื่อง[ 3 ] และความหมายของบิตจะไม่ขึ้นอยู่กับดัชนีตัวเลข[ 2 ]

การดำเนินการ

สามารถใช้ฟิลด์บิตเพื่อลดการใช้หน่วยความจำเมื่อโปรแกรมต้องการตัวแปรจำนวนเต็มจำนวนมากซึ่งจะมีค่าต่ำเสมอ ตัวอย่างเช่น ในหลายระบบ การจัดเก็บค่าจำนวนเต็มต้องใช้หน่วยความจำสองไบต์ (16 บิต) บางครั้งค่าที่จะจัดเก็บนั้นต้องการเพียงหนึ่งหรือสองบิตเท่านั้น การที่ตัวแปรขนาดเล็กเหล่านี้จำนวนมากใช้ฟิลด์บิตร่วมกันจะช่วยให้สามารถบรรจุข้อมูลในหน่วยความจำได้อย่างมีประสิทธิภาพ[ 5 ]

ในภาษา C ฟิลด์บิตที่กำหนดโดยการใช้งานดั้งเดิมสามารถสร้างได้โดยใช้int, [ a ]unsigned int ​​, signed int, _Bool(ในC99 ), _BitInt(N), unsigned _BitInt(N)(ในC23 ) หรือประเภทที่กำหนดโดยการใช้งานอื่นๆ ในภาษา C++ สามารถสร้างได้โดยใช้ประเภทจำนวนเต็มหรือประเภทการแจงนับใดๆ คอมไพเลอร์ C ส่วนใหญ่ก็อนุญาตเช่นกัน ในกรณีนี้ โปรแกรมเมอร์สามารถประกาศโครงสร้างสำหรับฟิลด์บิตซึ่งติดป้ายกำกับและกำหนดความกว้างของฟิลด์ย่อยหลายๆ ฟิลด์[ 6 ] จากนั้น คอมไพเลอร์สามารถบรรจุฟิลด์บิตที่ประกาศติดกันของประเภทเดียวกันลงในจำนวนคำที่ลดลง เมื่อเทียบกับหน่วยความจำที่ใช้หากแต่ละ 'ฟิลด์' ถูกประกาศแยกกัน

สำหรับภาษาที่ไม่มีฟิลด์บิตดั้งเดิม หรือในกรณีที่โปรแกรมเมอร์ต้องการควบคุมการแสดงบิตที่ได้ โปรแกรมเมอร์สามารถจัดการบิตด้วยตนเองภายในประเภทคำที่ใหญ่กว่าได้ ในกรณีนี้ โปรแกรมเมอร์สามารถตั้งค่า ทดสอบ และเปลี่ยนแปลงบิตในฟิลด์โดยใช้การผสมผสานระหว่างการมาสก์และ การ ดำเนินการบิต [ 7 ]

ตัวอย่าง

ซี

สามารถใช้บิตฟิลด์ภายในโครงสร้างในภาษา CและC++ได้[ 6 ]

#include <stdint.h>// ทึบแสงและแสดง ผล enum Visibility : uint8_t { NO = 0 , YES = 1 };// รูปแบบเส้นenum LineStyle : uint8_t { SOLID = 1 , DOTTED = 2 , DASHED = 3 };// สีenum Color : uint8_t { BLACK = 0 , RED = 0b001 , GREEN = 0b010 , BLUE = 0b100 , YELLOW = RED | GREEN , // 011 MAGENTA = RED | BLUE , // 101 CYAN = GREEN | BLUE , // 110 WHITE = RED | GREEN | BLUE // 111 };const char * colors [ 8 ] = { "Black" , "Red" , "Green" , "Yellow" , "Blue" , ​​"Magenta" , "Cyan" , "White" };// คุณสมบัติของกล่องบิตฟิลด์struct BoxProps { uint32_t opaque : 1 ; uint32_t fill_color : 3 ; [[ maybe_unused ]] uint32_t filler_a : 4 ; // เติมให้ครบ 8 บิตuint32_t แสดงเส้นขอบ: 1 ; uint32_t สีเส้นขอบ: 3 ; uint32_t รูปแบบเส้นขอบ: 2 ;[[ maybe_unused ]] uint8_t filler_b : 0 ; // เติมค่าให้ใกล้เคียงที่สุดเป็นไบต์ (16 บิต)uint8_t width : 4 ; // แบ่งไบต์ออกเป็น 2 ฟิลด์ ฟิลด์ละ 4 บิตuint8_t height : 4 ; };int main ( ) { BoxProps my_box = { .opaque = YES , .fill_color = RED , .show_border = YES , .border_color = BLUE , .border_style = SOLID , .width = 5 , .height = 10 } ; }

โครงสร้างของฟิลด์บิตในภาษาซีstructนั้น ขึ้นอยู่กับ การใช้งานของแต่ละคอมไพเลอร์เพื่อให้ได้พฤติกรรมที่คาดเดาได้ในคอมไพเลอร์ต่างๆ อาจเป็นการดีกว่าที่จะจำลองฟิลด์บิตด้วยฟังก์ชันพื้นฐานและตัวดำเนินการบิต:

#include <stdint.h>/** * คำสั่งพรีโปรเซสเซอร์แต่ละคำสั่งนี้กำหนดบิตเดียว* ซึ่งสอดคล้องกับปุ่มหนึ่งปุ่มบนคอนโทรลเลอร์ * ลำดับปุ่มตรงกับของเครื่องเล่นเกม Nintendo Entertainment System */ enum Key : uint8_t { KEY_RIGHT = 0b00000001 , KEY_LEFT = 0b00000010 , KEY_DOWN = 0b00000100 , KEY_UP = 0b00001000 , KEY_START = 0b00010000 , KEY_SELECT = 0b00100000 , KEY_B = 0b01000000 , KEY_A = 0b10000000 };// สถานะทั่วโลกuint8_t gameControllerStatus = 0 ;// กำหนดค่า gameControllerStatus โดยใช้ OR void onKeyPressed ( uint8_t key ) { gameControllerStatus |= key ; }// ล้างค่า gameControllerStatus โดยใช้ AND และ ~ (ไบนารี NOT) void onKeyReleased ( uint8_t key ) { gameControllerStatus &= ~ key ; }// ทดสอบว่าบิตถูกตั้งค่าหรือไม่โดยใช้ AND uint8_t isPressed ( uint8_t key ) { return gameControllerStatus & key ; }

สนิม

แม้ว่าRustจะไม่มีฟิลด์บิตแบบเดียวกับในภาษา C แต่ก็สามารถใช้มาสก์มาทดแทนได้

impl BoxProps { // ไบต์ 0 const OPAQUE : u8 = 0b0000_0001 ; const FILL_COLOR_MASK : u8 = 0b0000_1110 ;// ไบต์ที่ 1 const SHOW_BORDER : u8 = 0b0000_0001 ; const BORDER_COLOR_MASK : u8 = 0b0000_1110 ; const BORDER_STYLE_MASK : u8 = 0b0011_0000 ;// ไบต์ที่ 2 const WIDTH_MASK : u8 = 0b0000_1111 ; const HEIGHT_MASK : u8 = 0b1111_0000 ; }impl BoxProps { fn opaque ( & self ) -> bool { self . raw [ 0 ] & Self :: OPAQUE != 0 }fn set_opaque ( & mut self , v : bool ) { self . raw [ 0 ] = ( self . raw [ 0 ] & ! Self :: OPAQUE ) | ( v as u8 ); }fn fill_color ( & self ) -> u8 { ( self . raw [ 0 ] & Self :: FILL_COLOR_MASK ) >> 1 }fn set_fill_color ( & mut self , v : u8 ) { self . raw [ 0 ] = ( self . raw [ 0 ] & ! Self :: FILL_COLOR_MASK ) | (( v & 0b111 ) << 1 ); }fn width ( & self ) -> u8 { self . raw [ 2 ] & Self :: WIDTH_MASK }fn height ( & self ) -> u8 { ( self . raw [ 2 ] & Self :: HEIGHT_MASK ) >> 4 } }

รีจิสเตอร์สถานะโปรเซสเซอร์

รีจิสเตอร์สถานะของโปรเซสเซอร์เป็นฟิลด์บิตที่ประกอบด้วยบิตแฟล็กหลายบิต แต่ละบิตแฟล็กจะอธิบายข้อมูลเกี่ยวกับสถานะปัจจุบันของโปรเซสเซอร์[ 8 ]ตัวอย่างเช่น รีจิสเตอร์สถานะของ โปรเซสเซอร์ 6502แสดงอยู่ด้านล่าง:

ทะเบียนสถานะ 6502
บิต 7บิต 6บิต 5บิต 4บิต 3บิต 2บิตที่ 1บิต 0
ธงลบธงการไหลย้อนกลับ-ธงระเบิดธงเลขฐานสิบแฟล็กปิดใช้งานการขัดจังหวะธงซี อีโอCถือธง

บิตเหล่านี้ถูกตั้งค่าโดยโปรเซสเซอร์หลังจากผลลัพธ์ของการดำเนินการ บิตบางบิต (เช่น ตัวบ่งชี้การทด (Carry), ตัวบ่งชี้การปิดใช้งานการขัดจังหวะ (Interrupt-disable) และตัวบ่งชี้ทศนิยม (Decimal) อาจถูกควบคุมอย่างชัดเจนโดยใช้คำสั่งตั้งค่าและล้างค่า นอกจากนี้ ยังมีการกำหนดคำสั่งแยกสาขาเพื่อเปลี่ยนแปลงการทำงานตามสถานะปัจจุบันของตัวบ่งชี้ด้วย

ตัวอย่างเช่น หลังจากADCคำสั่ง (Add with Carry) แล้ว BVSอาจใช้คำสั่ง (Branch on oVerflow Set) เพื่อกระโดดไปยังตำแหน่งถัดไปโดยพิจารณาว่า โปรเซสเซอร์ได้ตั้งค่า แฟล็กโอเวอร์โฟลว์ ไว้หรือ ไม่หลังจากผลลัพธ์ของคำสั่งบวก

การดึงบิตจากคำธง

สามารถแยกชุดย่อยของแฟล็กในฟิลด์แฟล็กได้โดยใช้ การดำเนินการ ANDกับมาสก์ภาษาโปรแกรมจำนวนมากรองรับ ตัวดำเนิน การเลื่อนบิต (<<) ซึ่ง1 << nจะจัดตำแหน่งบิตเดียวให้ตรงกับตำแหน่งที่ n ภาษาโปรแกรมส่วนใหญ่ยังรองรับการใช้ ตัวดำเนินการ AND (&) เพื่อแยกค่าของบิตหนึ่งบิตหรือมากกว่านั้น

ถ้าไบต์สถานะจากอุปกรณ์คือ 0x67 และบิตแฟล็กที่ 5 ระบุว่าข้อมูลพร้อมใช้งาน ไบต์มาสก์คือ 0 2^5 = 0x20การนำไบต์สถานะ 0x67 ( ในเลขฐานสอง) มาทำการ AND0110 0111กับไบต์มาสก์ 0x20 ( 0010 0000ในเลขฐานสอง) จะได้ผลลัพธ์เป็น 0x20 ซึ่งหมายความว่าบิตแฟล็กถูกตั้งค่า นั่นคือ อุปกรณ์มีข้อมูลพร้อมใช้งาน ถ้าบิตแฟล็กไม่ได้ถูกตั้งค่า ผลลัพธ์จะเป็น 0 นั่นคือ ไม่มีข้อมูลพร้อมใช้งานจากอุปกรณ์

ในการตรวจสอบบิตที่nจากตัวแปรvให้ดำเนินการอย่างใดอย่างหนึ่งต่อไปนี้ (ทั้งสองวิธีให้ผลลัพธ์ที่เทียบเท่ากัน)

bool nth_is_set = ( v & ( 1 << n )) != 0 ; bool nth_is_set = ( v >> n ) & 1 ;

การเปลี่ยนบิตในคำของธง

การเขียน การอ่าน หรือการสลับบิตในแฟล็ก สามารถทำได้โดยใช้การดำเนินการ OR, AND และ NOT เท่านั้น ซึ่งเป็นการดำเนินการที่โปรเซสเซอร์สามารถดำเนินการได้อย่างรวดเร็ว ในการตั้งค่าบิต ให้ใช้การดำเนินการORระหว่างไบต์สถานะกับไบต์มาสก์ บิตใดๆ ที่ตั้งค่าไว้ในไบต์มาสก์หรือไบต์สถานะจะถูกตั้งค่าในผลลัพธ์

ในการสลับสถานะของบิต ให้ใช้การดำเนินการXORระหว่างไบต์สถานะและไบต์มาสก์ การดำเนินการนี้จะตั้งค่าบิตหากบิตนั้นถูกล้าง หรือล้างบิตหากบิตนั้นถูกตั้งค่าไว้

ดูเพิ่มเติม

หมายเหตุ

  1. ^ในภาษา C นั้น การกำหนดว่าบิตฟิลด์ชนิด int จะเป็นแบบมีเครื่องหมายหรือไม่มีเครื่องหมายนั้นขึ้นอยู่กับการใช้งาน ในภาษา C++ นั้น จะเป็นแบบมีเครื่องหมายเสมอเพื่อให้ตรงกับชนิดข้อมูลพื้นฐาน
  • คำอธิบายจากหนังสือ
  • คำอธิบายจากวิกิอื่น
  • กรณีศึกษาในคู่มือ C++
  • ไลบรารีบิต C ++ libbit ( URL ทางเลือก )
  • เทคนิคการจัดการบิต : ตัวอย่างโค้ดภาษาซีหลายส่วนที่ใช้สำหรับจัดการฟิลด์บิต
ดึงข้อมูลมาจาก " https://en.wikipedia.org/w/index.php?title=Bit_field&oldid=1359011348 "

สรุปเนื้อหา

ข้อมูลสำคัญจากบทความ

ข้อมูลสำคัญเกี่ยวกับ บิตฟิลด์

ฟิลด์ บิต เป็น โครงสร้างข้อมูล ที่แมปกับ บิต ที่อยู่ติดกันตั้งแต่หนึ่งบิตขึ้นไปซึ่งได้รับการจัดสรรไว้เพื่อวัตถุประสงค์เฉพาะ...

การดำเนินการ

สามารถใช้ฟิลด์บิตเพื่อลดการใช้หน่วยความจำเมื่อโปรแกรมต้องการตัวแปรจำนวนเต็มจำนวนมากซึ่งจะมีค่าต่ำเสมอ ตัวอย่างเช่น ในหลายระบบ การจัดเก็บค่าจำนวนเต็มต้องใช้หน่วยความจำสองไบต์ (16 บิต) บางครั้งค่าที่จะจัดเก็บนั้นต้องการเพียงหนึ่งหรือสองบิตเท่านั้น...

ซี

สามารถใช้บิตฟิลด์ภายในโครงสร้างใน ภาษา C และ C++ ได้ [ 6 ]

สนิม

แม้ว่า Rust จะไม่มีฟิลด์บิตแบบเดียวกับในภาษา C แต่ก็สามารถใช้มาสก์มาทดแทนได้