بتفيلد

حقل البت هو بنية بيانات تُشير إلى بت واحد أو أكثر من البتات المتجاورة المُخصصة لأغراض مُحددة، بحيث يُمكن ضبط أو فحص أي بت مُفرد أو مجموعة بتات داخل البنية. [ 1 ] [ 2 ] يُستخدم حقل البت في أغلب الأحيان لتمثيل أنواع البيانات الصحيحة ذات عرض البت الثابت والمعروف، مثل القيم المنطقية أحادية البت .

يُحدد المبرمج معنى البتات الفردية داخل الحقل؛ على سبيل المثال، يُستخدم البت الأول في حقل البتات (الموجود في عنوان القاعدة للحقل ) أحيانًا لتحديد حالة سمة معينة مرتبطة بحقل البتات. [ 3 ]

في وحدات المعالجة المركزية وغيرها من الأجهزة المنطقية، تُستخدم مجموعات من حقول البتات تُسمى الرايات للتحكم في نتائج عمليات معينة أو للإشارة إليها. [ 4 ] تحتوي المعالجات على سجل حالة مُكوّن من رايات. على سبيل المثال، إذا تعذّر تمثيل نتيجة عملية جمع في الوجهة، يتم ضبط تجاوز حسابي . يمكن استخدام الرايات لتحديد العمليات اللاحقة، مثل تعليمات القفز الشرطي . على سبيل المثال، ستؤدي تعليمة (القفز إذا كان يساوي) في لغة التجميع x86 إلى قفزة إذا تم ضبط الراية Z (صفر) بواسطة عملية سابقة.JE...

يُفرَّق حقل البت عن مصفوفة البت في أن الأخيرة تُستخدم لتخزين مجموعة كبيرة من البتات المفهرسة بأعداد صحيحة، وغالبًا ما يكون عرضها أكبر من أي نوع صحيح تدعمه اللغة. أما حقول البت، من ناحية أخرى، فتُناسب عادةً كلمة الآلة ، [ 3 ] ويكون دلالة البتات مستقلة عن فهرسها العددي. [ 2 ]

تطبيق

يمكن استخدام حقول البت لتقليل استهلاك الذاكرة عندما يتطلب البرنامج عددًا من المتغيرات الصحيحة التي ستكون قيمها منخفضة دائمًا. على سبيل المثال، في العديد من الأنظمة، يتطلب تخزين قيمة عددية بايتين (16 بتًا) من الذاكرة؛ بينما في بعض الأحيان لا تحتاج القيم المراد تخزينها إلا إلى بت واحد أو اثنين. يتيح وجود عدد من هذه المتغيرات الصغيرة التي تشترك في حقل بت واحد تنظيمًا فعالًا للبيانات في الذاكرة. [ 5 ]

في لغة C، يمكن إنشاء حقول البتات المُعرَّفة حسب التنفيذ باستخدام أنواع البيانات التالية int: ` <td> `unsigned int ، ` <td> signed int`، `<td> _Bool` (في C99_BitInt(N)` unsigned _BitInt(N)<td>`، `<td>` (في C23 )، أو أنواع أخرى مُعرَّفة حسب التنفيذ. أما في لغة C++، فيمكن إنشاؤها باستخدام أي نوع عدد صحيح أو تعداد؛ كما تسمح معظم مُجمِّعات لغة C بذلك. في هذه الحالة، يستطيع المبرمج تعريف بنية لحقل بتات تُحدِّد عرض عدة حقول فرعية. [ 6 ] وبذلك ، يُمكن للمُجمِّع ضغط حقول البتات المُعرَّفة بشكل متجاور من نفس النوع في عدد أقل من الكلمات، مقارنةً بالذاكرة المُستخدمة في حال تعريف كل حقل على حدة.

بالنسبة للغات التي تفتقر إلى حقول بت أصلية، أو عندما يرغب المبرمج في التحكم في تمثيل البت الناتج، فمن الممكن معالجة البتات يدويًا ضمن نوع كلمة أكبر. في هذه الحالة، يمكن للمبرمج ضبط البتات في الحقل واختبارها وتغييرها باستخدام مجموعات من عمليات الإخفاء والعمليات المنطقية على مستوى البت . [ 7 ]

أمثلة

ج

يمكن استخدام حقول البت داخل الهياكل في لغتي C و C++ . [ 6 ]

#include <stdint.h>// تعداد معتم وإظهار الرؤية : uint8_t { NO = 0 , YES = 1 };// أنماط الخطوط enum LineStyle : uint8_t { SOLID = 1 , DOTTED = 2 , DASHED = 3 };// تعداد الألوان Color : uint8_t { أسود = 0 ، أحمر = 0b001 ، أخضر = 0b010 ، أزرق = 0b100 ، أصفر = أحمر | أخضر ، // 011 أرجواني = أحمر | أزرق ، // 101 سماوي = أخضر | أزرق ، // 110 أبيض = أحمر | أخضر | أزرق // 111 };const char * colors [ 8 ] = { "أسود" , "أحمر" , "أخضر" , "أصفر" , "أزرق" , "أرجواني" , "سماوي" , "أبيض" };// خصائص صندوق الحقول الثنائية struct BoxProps { uint32_t opaque : 1 ; uint32_t fill_color : 3 ; [[ maybe_unused ]] uint32_t filler_a : 4 ; // التعبئة إلى 8 بتاتuint32_t show_border : 1 ; uint32_t border_color : 3 ; uint32_t border_style : 2 ;[[ ربما غير مستخدم ]] uint8_t filler_b : 0 ; // املأ إلى أقرب بايت (16 بت)uint8_t width : 4 ; // تقسيم بايت إلى حقلين من 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يُحدد تصميم حقول البت في لغة C بواسطة التنفيذ . وللحفاظ على سلوك قابل للتنبؤ عبر مختلف المترجمات، قد يكون من الأفضل محاكاة حقول البت باستخدام نوع بيانات أساسي ومعاملات بت.

#include <stdint.h>/** * يُعرّف كل توجيه من توجيهات المعالج المسبق هذه بتًا واحدًا، * يُقابل زرًا واحدًا على وحدة التحكم. * ترتيب الأزرار مطابق لترتيب نظام نينتندو الترفيهي. */ 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 ;// يُعيّن حالة وحدة تحكم اللعبة باستخدام OR void onKeyPressed ( uint8_t key ) { gameControllerStatus |= key ; }// يمسح حالة وحدة التحكم في اللعبة باستخدام 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
علامة سلبية Nعلامة تجاوز السعة-علم الفراملعلامة عشريةعلامة تعطيل المقاطعةعلم زيروحمل العلم

تُضبط هذه البتات بواسطة المعالج بعد انتهاء العملية. ويمكن التحكم ببعض البتات (مثل بت الحمل، وبت تعطيل المقاطعة، وبت الفاصلة العشرية) بشكل صريح باستخدام تعليمات الضبط والمسح. بالإضافة إلى ذلك، تُعرَّف تعليمات التفرع لتغيير التنفيذ بناءً على الحالة الحالية للبت.

على سبيل المثال، بعد ADCتعليمة (الجمع مع الحمل)، BVSيمكن استخدام تعليمة (التفرع عند تعيين تجاوز السعة) للقفز بناءً على ما إذا كان المعالج قد قام بتعيين علامة تجاوز السعة بعد نتيجة تعليمة الجمع.

استخراج أجزاء من كلمات العلامات

يمكن استخراج مجموعة فرعية من العلامات في حقل العلامات عن طريق عملية AND مع قناع . يدعم عدد كبير من لغات البرمجة عامل الإزاحة ( << ) الذي يُحاذي بتًا واحدًا إلى الموضع النوني. كما تدعم معظمها استخدام عامل AND (&) لعزل قيمة بت واحد أو أكثر.1 << n

إذا كانت قيمة بايت الحالة من جهاز ما هي 0x67، وكان بت العلم الخامس يشير إلى جاهزية البيانات، فإن قيمة بايت القناع هي 0x20 2^5 = 0x20. وبإجراء عملية AND بين بايت الحالة 0x67 ( بالنظام الثنائي) وبايت القناع 0x20 ( بالنظام الثنائي)، تكون النتيجة 0x20. هذا يعني أن بت العلم مُفعّل، أي أن الجهاز لديه بيانات جاهزة. أما إذا لم يكن بت العلم مُفعّلاً، فستكون النتيجة 0، أي أنه لا توجد بيانات متاحة من الجهاز.0110 01110010 0000

للتحقق من البت رقم 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++، فهو مُوقّع دائمًا ليتوافق مع النوع الأساسي.

مراجع

  1. بن بروم؛ دون بروم (أغسطس 1988). لغة التجميع 80386: دليل شامل ومكتبة للبرامج الفرعية . مجموعة ماكجرو هيل التعليمية المدرسية. ص  606. ISBN 978-0-8306-9047-3.
  2. 1 2 ستيف أوالين (1997). البرمجة العملية بلغة سي . دار نشر أورايلي ميديا، ص 403 وما يليها. رقم ISBN  978-1-56592-306-5.
  3. 1 2 مايكل أ. ميلر (يناير 1992). عائلة المعالجات الدقيقة 68000: البنية، والبرمجة، والتطبيقات . ميريل. ص 323. ISBN  978-0-02-381560-7.
  4. إيان غريفيث؛ ماثيو آدامز؛ جيسي ليبرتي (30 يوليو 2010). برمجة C# 4.0: بناء تطبيقات ويندوز، والويب، وتطبيقات RIA لإطار عمل .NET 4.0 . دار نشر أورايلي ميديا، الصفحات 81 وما بعدها. ISBN  978-1-4493-9972-6.
  5. تيبت ميمار (1991). البرمجة والتصميم باستخدام عائلة 68000: بما في ذلك 68000 و68010/12 و68020 و68030 . برنتيس هول. ص 275. ISBN  978-0-13-731498-0.
  6. 1 2 براتا، ستيفن (2007). C التمهيدي زائد (الطبعة الخامسة ). إنديانابوليس، إنديانا: سامز. رقم ISBN  978-0-672-32696-7.
  7. ^ مارك إي داجيت (13 نوفمبر 2013). جافا سكريبت الخبراء . Apress. ص 68–. رقم ISBN  978-1-4302-6097-4.
  8. InCider . دبليو. جرين. يناير 1986. ص 108.