لغة سي المضمّنة: Struct و Union

في هذا المقال سنتحدث عن بنى معطيات متقدمة في لغة C وهي struct و union. إن استيعاب كيفية التعامل مع أنواع المعطيات هذه أساسي في برمجة C بشكل عام، لكنها أكثر أهمية في برمجة المتحكمات والبرمجة المضمنة embedded programming لأنها تعطي المطور إمكانيات تسهل كتابة البرامج المضمنة بشكل خاص.

البنى structures أو struct

يمكن النظر إلى البنية structure على أنها وسيلة لتجميع عدد من المتحولات ذات أنواع مختلفة في كيان واحد يبدأ بعنوان واحد في الذاكرة. يشار إلى البنية في لغة C بـ struct:

ملاحظة: انتبه للفاصلة المنقوطة بنهاية التعريف

تسمى المتحولات المختلفة داخل البنية بعناصر البنية أو members.  البنية struct بحد ذاتها هي نوع من أنواع المتحولات ولكنها تختلف عن غيرها بأنها متحولات مخصصة custom فبعد أن يتم تعريف الـ struct يمكن عندها انشاء متحولات من نوع الـ struct الجديدة:

يمكنك أيضاً التصريح declare وتعريف متحول define من نوع strcut في آن واحد كما يلي:

يمكن الآن الوصول لأجزاء البنية members  باستخدام النقطة “.” في المتحولات العادية :

أما في حالة المؤشرات فنستخدم “<-“

ملاحظة:الـ struct  نفسها عبارة عن قالب template فقط ولا يقوم الـ compiler بتخصيص أي جزء من الذاكرة عند تعريف البنية struct  وإنما يقوم بذلك فقط عند تعريف متحول من نوع الـ struct الجديدة:

(استخدام كلمة struct هنا إلزامي و سنبين طريقة للتخلص منها لاحقاً في التدوينة)

أحياناً لا نحتاج إلا لعدد معين من البتات لتخزين القيم في عناصر البنية، وفي هذه الحالة يمكن استخدام حقول البت bit fields والتي صممت من أجل تخفيض مساحة التخزين المطلوبة إلى حدها الأدنى ويمكن تعريف حقول البت هذه باستخدام عناصر من أعداد صحيحة int ويتم تحديد عدد البتات باستخدام “:” كما يلي:

في المثال السابق element_a بطول بت واحد و element_b بطول ثلاث بتات وelement_c بطول 2 بت وبقيمة افتراضية 0.

على الرغم أن استخدام الـbit fields ليس موصى به لأنه يعد غير مرجعي standard بين المترجمات compilers المختلفة حيث يمكن أن يختلف طريقة التعامل معه ولكنه يبقى أحد التقنيات المستخدمة ولكن يجب أن تكون مراعياً لهذه الجزئيّة.

الـ union

في بعض الأحيان نحتاج لمتحول نستطيع النفاذ له بطرق (أنواع معطيات) مختلفة ولكن في بمساحة تخزينيّة واحدة أي دون وجود حاجة لتكرار مساحة التخزين وهنا يأتي دور الـ union.

إن طريقة تعريف الـ union مشابهة لطريقة تعريف البنية struct

أيضا طريقة الوصول لقيمة أحد العناصر مشابه تماما للبنية

وفي حالة المؤشرات

الفارق الأساسي بين النوعين هو طريقة تخزين البيانات فالـ union يحجز مكانا في الذاكرة بمقدار أطول عنصر من عناصر الـ union على عكس الـ struct والتي تحجز بمقدار مجموع جميع العناصر.

struct vs union

قد لايكون استخدام الـ union كبيرا في الأنظمة البرمجية إلا أن استخدامه مهم جداً في الأنظمة المضمنة فهو غالباً مايستخدم كنوع من الذاكرة المؤقتة (مسودة) لتخزين قيم ذات أنواع مختلفة في مكان الذاكرة ذاته عندما لا نحتاج استخدام اثنين من هذه القيم في الوقت ذاته والاستخدام بهذا الشكل يساعد في تخفيض الذاكرة التي يحتاجها البرنامج وهذا من أهم العوامل في البرمجة المضمنة كما هو معروف.

الاستخدام الرائج الآخر هو تسهيل استخراج قيم أصغر من قيمة كلية أكبر كما في المثال

في المثال السابق يمكن الوصول للقيمة الكلية كـ32 بت دفعة واحدة TMR.val أو باستخدام أجزاء أصغر TMR.Bytes.Zero.

استخدام التعليمة typedef مع struct أو union

تسمح لغة C بإعطاء اسم بديل  جديد بناءً على أنواع المتحولات المعروفة باستخدام التعليمة typedef فمثلاً

 

هنا قمنا بتعريف اسم بديل alias هو ulong بدلاًعن النوع unsigned long والآن يمكننا استخدام هذا الـ alias لتعريف متحول باسم var  له النوع unsigned long كما يلي:

 

يعالج ال compiler هذه التعليمة بينما التعليمة #define المشابهة لعملها فيتعامل معها المعالج البدائي preprocessor كما تحدثنا في مقالة سابقة بشكل تفصيلي.

نفس الفكرة يمكن تطبيقها مع struct أو union. سنأخذ مثال على struct:

الآن يمكن استخدام sname لتعريف متحولات s1,s2 من نوع الـ struct السابق كما يلي:

بنفس الطريقة تماما يمكن استخدام الـ typedef مع الـ union.

المراجع

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *