متغير خارجي

في لغة البرمجة C ، وسابقتها B ، يُعرَّف المتغير الخارجي بأنه متغير مُعرَّف خارج أي كتلة دالة. أما المتغير المحلي (التلقائي) فهو متغير مُعرَّف داخل كتلة دالة.

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

التعريف والإعلان والكلمة externالمفتاحية

خارجي

في B، يجب تعريف جميع المتغيرات، إما كـ auto extrnأو ضمنيًا كوسائط للدوال. [ 1 ] يُعرَّف المتغير الخارجي خارج الدوال، ويكون عمره طوال مدة تنفيذ البرنامج، ويُدخل إلى الدالة عن طريق extrnالتعريف.

باستخدام الكود التالي في البرنامج التعليمي كمثال: [ 1 ]

main ( ) { extrn a , b , c ; putchar ( a ); putchar ( b ); putchar ( c ); putchar ( ' !* n ' ); }أ ' الجحيم ' ؛ ب ' العالم ' ؛ ج ' العالم ' ؛

a، b، cهي جميعها متغيرات خارجية للبرنامج تم تعريفها خارج الدوال، وتم إدخالها إلى mainالدالة عن طريق extrnالتصريحات.

خارجي

لفهم كيفية ارتباط المتغيرات الخارجية بالكلمة externالمفتاحية، من الضروري معرفة الفرق بين تعريف المتغير وإعلانه. عند تعريف متغير ، يُخصص المُصرّف مساحة في الذاكرة لهذا المتغير، وقد يُهيئ محتوياته بقيمة مُعينة. أما عند إعلان متغير ، فيشترط المُصرّف تعريفه في مكان آخر. يُعلم الإعلان المُصرّف بوجود متغير بهذا الاسم والنوع، لكن المُصرّف لا يحتاج إلى تخصيص مساحة له في الذاكرة لأنه مُخصص في مكان آخر. externتعني الكلمة المفتاحية "الإعلان دون تعريف". بعبارة أخرى، هي طريقة لإعلان متغير بشكل صريح، أو فرض إعلان دون تعريف. من الممكن أيضًا تعريف متغير بشكل صريح، أي فرض تعريف. يتم ذلك عن طريق إسناد قيمة ابتدائية للمتغير. إذا لم تكن الكلمة externالمفتاحية أو قيمة الابتدائية موجودة، فيمكن أن تكون العبارة إعلانًا أو تعريفًا. يعود الأمر إلى المُصرّف لتحليل وحدات البرنامج واتخاذ القرار.

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

يمكن أيضًا تعريف متغير خارجي داخل دالة. في هذه الحالة، externيجب استخدام الكلمة المفتاحية `external`، وإلا سيعتبره المترجم تعريفًا لمتغير محلي ( تلقائي )، والذي له نطاق وعمر وقيمة ابتدائية مختلفة. سيكون هذا التعريف مرئيًا داخل الدالة فقط، وليس في جميع أنحاء وحدة الدالة.

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

يجب تعريف المتغير الخارجي مرة واحدة فقط، خارج أي دالة؛ وهذا يُخصص له مساحة تخزين. كما يجب تعريف المتغير في كل دالة ترغب في الوصول إليه؛ وهذا يُحدد نوعه. قد يكون التعريف صريحًا externأو ضمنيًا من السياق. ... تجدر الإشارة إلى أننا نستخدم مصطلحي "التعريف" و"الإعلان" بدقة عند الحديث عن المتغيرات الخارجية في هذا القسم. يشير "التعريف " إلى المكان الذي يُنشأ فيه المتغير أو تُخصص له مساحة تخزين؛ بينما يشير "الإعلان" إلى الأماكن التي تُحدد فيها طبيعة المتغير دون تخصيص مساحة تخزين له.

النطاق، العمر الافتراضي، والكلمة staticالمفتاحية

يمكن الوصول إلى المتغير الخارجي من جميع الدوال في جميع وحدات البرنامج. إنه متغير عام . لكي تتمكن دالة ما من استخدام هذا المتغير، يجب أن يسبق تعريف المتغير الخارجي تعريف الدالة في الكود المصدري. أو يجب تعريف المتغير، باستخدام الكلمة المفتاحية `$` extern، داخل الدالة نفسها.

إن استخدام الكلمة staticالمفتاحية ( staticوهما externمتنافيان) عند تعريف متغير خارجي يُغير هذا الأمر قليلاً: إذ لا يمكن الوصول إلى المتغير إلا من خلال الدوال الموجودة في نفس الوحدة التي تم تعريفه فيها. ولكن من الممكن لدالة في نفس الوحدة أن تُمرر مرجعًا (مؤشرًا) للمتغير إلى دالة أخرى في وحدة أخرى. في هذه الحالة، حتى وإن كانت الدالة في وحدة أخرى، فإنها تستطيع قراءة محتويات المتغير وتعديلها ، ولكن لا يمكنها الإشارة إليه بالاسم.

من الممكن أيضًا استخدام staticالكلمة المفتاحية `automatic` في تعريف متغير محلي . بدون هذه staticالكلمة، يُخصص المتغير تلقائيًا عند استدعاء الدالة ويُحرر عند انتهائها (ومن هنا جاء اسم "المتغير التلقائي"). ولا تُحفظ قيمته بين استدعاءات الدالة. أما مع الكلمة staticالمفتاحية `automatic`، فيُخصص المتغير عند بدء البرنامج ويُحرر عند انتهائه. ولا تُفقد قيمته بين استدعاءات الدالة. ويظل المتغير محليًا، إذ لا يمكن الوصول إليه إلا بالاسم داخل الدالة التي عرّفته. ولكن يمكن تمرير مرجع (مؤشر) إليه إلى دالة أخرى، مما يسمح لها بقراءة محتويات المتغير وتعديلها (مرة أخرى دون الحاجة إلى الإشارة إليه بالاسم).

يتم تخصيص المتغيرات الخارجية وتهيئتها عند بدء تشغيل البرنامج، ولا يتم تحرير الذاكرة إلا عند انتهاء البرنامج. ويكون عمرها مماثلاً لعمر البرنامج.

إذا لم تتم عملية التهيئة بشكل صريح، فسيتم تهيئة المتغيرات الخارجية (الثابتة أو غير الثابتة) والمتغيرات الثابتة المحلية إلى الصفر. أما المتغيرات التلقائية المحلية فتبقى غير مهيأة، أي أنها تحتوي على قيم "غير مهمة".

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

مثال (لغة البرمجة سي)

الملف 1:

// تعريف صريح، هذا يقوم فعلياً بتخصيص // بالإضافة إلى وصف متغير عام من نوع int ;// نموذج الدالة (التصريح)، يفترض // أنها معرفة في مكان آخر، عادةً من ملف التضمين. void someFunction ( void );int main ( void ) { global_variable = 1 ; someFunction (); return 0 ; }

الملف 2:

// إعلان ضمني، هذا يصف فقط ويفترض // أنه تم تخصيصه في مكان آخر، عادةً من تضمين extern int global_variable ;// تعريف الدالة (رأس الدالة) void someFunction ( void ) { ++ global_variable ; }

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

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

تتمثل المنهجية المعتادة في تخصيص الذاكرة والتعريفات الفعلية في ملفات .c، ولكن مجرد التصريحات والنماذج الأولية لا تقوم بتخصيص الذاكرة وتصف فقط الأنواع والمعلمات حتى يتمكن المترجم من العمل بشكل صحيح، وهذه المعلومات تنتمي إلى ملف رأس .h يمكن للآخرين تضمينه بأمان دون أي تعارض محتمل.

انظر أيضاً

  • الإعلان – بنية لغة برمجة تحدد خصائص المعرف 
  • نموذج الدالة – ​​تعريف اسم الدالة وتوقيع نوعها، ولكن ليس جسم الدالة 
  • المتغير العام – في برمجة الحاسوب، وهو متغير يمكن الوصول إليه في جميع أنحاء برنامج الحاسوب 
  • الرابط (الحوسبة) - برنامج يجمع ملفات البناء الوسيطة في ملف قابل للتنفيذ 
  • المتغير المحلي – في برمجة الحاسوب، متغير لا يمكن استخدامه إلا في جزء من البرنامج (النطاق) 
  • النطاق – جزء من برنامج حاسوبي حيث يكون ربط اسم معين صالحًا. صفحات تعرض أوصافًا مختصرة لأهداف إعادة التوجيه 
  • المتغير الثابت – متغير برمجي يبقى موجودًا طوال فترة تشغيل البرنامج 
  • لغة البرمجة سي – كتاب من تأليف برايان كيرنيغان ودينيس ريتشي 

مراجع

  1. 1 2 Kernighan, BW مقدمة تعليمية للغة ب . موراي هيل، نيو جيرسي: مختبرات بيل.