0Pricing
C Academy · درس

extern والربط

شارك الرموز بين الملفات

extern والربط درس مجاني في C Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C Academy 4 دروس في المجموع.

ما هو الربط؟

يصف الربط إمكانية مشاركة اسم بين ملفات مصدر مختلفة.

يشير الاسم ذو الربط الخارجي إلى الكيان نفسه عبر البرنامج بأكمله. أما الاسم ذو الربط الداخلي فيكون خاصًا بملفه. ويُعد فهم الربط أمرًا أساسيًا للبرامج متعددة الملفات.

مشاركة متغير

لنفترض أن ملفين يحتاجان إلى الوصول إلى عدّاد عام واحد. لا يمكنكم تعريفه ببساطة في كلا الملفين؛ فهذا ينشئ متغيرين منفصلين ويؤدي إلى خطأ ربط بسبب تكرار الرمز.

بدلًا من ذلك، تقومون بتعريفه مرة واحدة، ثم التصريح به في جميع المواضع الأخرى باستخدام extern.

/* config.c */
int g_count = 0;   /* the one definition */

الكلمة المفتاحية extern

تخبر extern المصرّف بأن متغيرًا ما موجود في موضع آخر من البرنامج، من دون إنشاء مساحة تخزين له هنا.

إنه تصريح فقط. ويحلّ الرابط هذا التصريح لاحقًا إلى التعريف الوحيد الموجود في ملف آخر.

/* other.c */
extern int g_count;   /* declared, not defined */

void bump(void) {
    g_count++;
}

التصريح في ملف الترويسة

النمط المنظم هو وضع تصريح extern في ملف ترويسة، ووضع التعريف المطابق في ملف مصدر واحد بالضبط.

بعد ذلك، يمكن لأي ملف يضمّن ملف الترويسة استخدام المتغير المشترك.

/* config.h */
#ifndef CONFIG_H
#define CONFIG_H
extern int g_count;
#endif

تعريف واحد وتصريحات متعددة

هذه هي قاعدة التعريف الواحد للمتغيرات العامة: يمكن التصريح عن متغير باستخدام extern في ملفات متعددة، ولكن يجب تعريفه في ملف واحد فقط.

يخصّص التعريف الوحيد، من دون extern، مساحة التخزين. أما جميع تصريحات extern فتشير إليه فحسب.

/* config.h */ extern int g_count;  /* declaration */
/* config.c */ int g_count = 0;     /* definition  */

للدوال أيضًا ربط خارجي

تملك الدوال أيضًا ربطًا خارجيًا افتراضيًا، ولذلك يتيح النموذج الأولي في ملف ترويسة للملفات الأخرى استدعاءها.

يمكنكم كتابة extern قبل النموذج الأولي، لكن ذلك زائد عن الحاجة؛ فالدوال خارجية ما لم تحددوا خلاف ذلك.

/* both forms mean the same */
int add(int a, int b);
extern int add(int a, int b);

الربط الداخلي باستخدام static

تمنح الكلمة المفتاحية static على مستوى الملف الاسمَ ربطًا داخليًا؛ أي إنه يكون مرئيًا داخل ملف المصدر الخاص به فقط.

استخدموها للدوال المساعدة والمتغيرات العامة التي ينبغي أن تظل خاصة بوحدة برمجية. لا تستطيع الملفات الأخرى رؤيتها أو حدوث تعارض بينها وبينها.

/* parser.c */
static int line_no = 0;   /* private to parser.c */

static void advance(void) {  /* private helper */
    line_no++;
}

extern مقابل static

تقع هاتان الكلمتان المفتاحيتان على طرفي نقيض من حيث الربط.

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

extern int shared_total;   /* visible everywhere */
static int local_cache;    /* only this file */

خطأ شائع

يضع المبتدئون أحيانًا تعريفًا عاديًا مثل int g_count; في ملف ترويسة.

ولأن ملف الترويسة يُضمَّن في عدة ملفات، يحصل كل ملف على تعريف خاص به، فيُبلغ الرابط عن رمز مكرر. احرصوا دائمًا على التصريح باستخدام extern في ملف الترويسة، والتعريف مرة واحدة في ملف .c.

/* WRONG in a header included twice */
int g_count;          /* multiple definition */
/* RIGHT */
extern int g_count;   /* declaration only */

جمع الأجزاء

هذا الشكل المؤلف من ثلاثة ملفات هو الطريقة القياسية لمشاركة الحالة.

تصرّح الترويسة، ويعرّفها ملف مصدر واحد، وتستخدمها الملفات الأخرى بعد تضمين الترويسة. ويربط الرابط جميع المراجع بالتعريف الوحيد.

/* config.h */ extern int g_count;
/* config.c */ #include "config.h"
               int g_count = 0;
/* main.c   */ #include "config.h"
               /* uses g_count */

ملاحظة حول التهيئة

ينبغي أن تعطي قيمة ابتدائية للتعريف الحقيقي فقط: int g_count = 0;.

يجب ألا يهيّئ تصريح extern المتغير، لأنه لا يخصّص مساحة تخزين. أما كتابة extern int g_count = 0; فتحوّله إلى تعريف وتلغي الغرض منه.

extern int g_count;       /* ok: declaration */
extern int g_count = 0;   /* becomes a definition */

تحقق سريع

تحققوا من فهمكم لـ extern والربط.

مراجعة

تعلمتم أن الربط يتحكم في إمكانية رؤية الأسماء بين الملفات. يصرّح extern عن اسم معرّف في موضع آخر، بينما يحافظ static على مستوى الملف على خصوصية الاسم.

شاركوا المتغيرات العامة باستخدام تعريف واحد وتصريحات extern. وسنقوم بعد ذلك بترجمة هذه الملفات وربطها في برنامج.

الأسئلة الشائعة

هل درس «extern والربط» مجاني؟

نعم — نص درس «extern والربط» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C Academy 4 دروس في المجموع.

ماذا ستتعلم في «extern والربط»؟

شارك الرموز بين الملفات تتمرن على C Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ C Academy؟

لا تُشترط خبرة سابقة. C Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «extern والربط»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس C Academy هذا؟

نعم. كل درس في C Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. ملفات الترويسة والمصدر
  2. حواجز التضمين
  3. extern والربط
  4. ترجمة ملفات متعددة
← العودة إلى C Academy