المعالجات هي البرامج التي تعالج الكود المصدري قبل بدء التجميع الفعلي. إنها ليست جزءًا من عملية التجميع ولكنها تعمل بشكل منفصل مما يسمح للمبرمجين بتعديل الكود قبل التجميع.
- إنها الخطوة الأولى التي يمر بها كود مصدر C عند تحويله إلى ملف قابل للتنفيذ.
- الأنواع الرئيسية لتوجيهات المعالج المسبق هي وحدات الماكرو التجميع الشرطي لإدراج الملف والتوجيهات الأخرى مثل #undef #pragma وما إلى ذلك.
- تُستخدم هذه التوجيهات بشكل أساسي لاستبدال قسم معين من كود C برمز C آخر. على سبيل المثال، إذا كتبنا "#define PI 3.14"، فسيتم استبدال PI بـ 3.14 بواسطة المعالج المسبق.
أنواع المعالجات C
يمكن تصنيف جميع المعالجات المذكورة أعلاه إلى 4 أنواع:
وحدات الماكرو
وحدات الماكرو تُستخدم لتحديد الثوابت أو إنشاء وظائف يتم استبدالها بواسطة المعالج المسبق قبل تجميع التعليمات البرمجية. المعالجين المسبقين #يُعرِّف و #undef تُستخدم لإنشاء وحدات الماكرو وإزالتها في لغة C.
#يُعرِّف قيمة رمزية
#undef رمز مميز
حيث بعد المعالجة المسبقة رمز مميز سيتم توسيعها إلى قيمة في البرنامج.
مثال:
C#include // Macro Definition #define LIMIT 5 int main(){ for (int i = 0; i < LIMIT; i++) { printf('%d n' i); } return 0; }
الإخراج
0 1 2 3 4
في البرنامج أعلاه قبل بدء التجميع، تم استبدال كلمة LIMIT بـ 5. الكلمة 'حد' في تعريف الماكرو يسمى قالب الماكرو و "5" هو التوسع الكلي.
ملحوظة لا توجد فاصلة منقوطة (؛) في نهاية تعريف الماكرو. لا تحتاج تعريفات الماكرو إلى فاصلة منقوطة حتى تنتهي.
هناك أيضا بعض وحدات الماكرو المحددة مسبقًا في C والتي تكون مفيدة في توفير وظائف مختلفة لبرنامجنا.
يمكن أن يكون الماكرو الذي تم تعريفه مسبقًا غير محدد باستخدام المعالج الأولي #undef. على سبيل المثال في الكود أعلاه
C#include // Macro Definition #define LIMIT 5 // Undefine macro #undef LIMIT int main(){ for (int i = 0; i < LIMIT; i++) { printf('%d n' i); } return 0; }
الإخراج:
./Solution.c: In function 'main': ./Solution.c:13:28: error: 'MAX' undeclared (first use in this function) printf('MAX is: %dn' MAX); ^ ./Solution.c:13:28: note: each undeclared identifier is reported only once for each function it appears inوحدات الماكرو مع الحجج
يمكننا أيضًا تمرير الوسائط إلى وحدات الماكرو. تعمل وحدات الماكرو هذه بشكل مشابه للوظائف. على سبيل المثال
# يُعرِّف فو (أ ب) أ + ب
#تعريف func(r) r * rحاول التقاط جافا
دعونا نفهم هذا مع برنامج:
C#include // macro with parameter #define AREA(l b) (l * b) int main(){ int a = 10 b = 5; // Finding area using above macro printf('%d' AREA(a b)); return 0; }
الإخراج
Area of rectangle is: 50
توضيح: في البرنامج أعلاه الماكرو المنطقة (ل ب) يتم تعريفه لحساب مساحة المستطيل بضربه الطول (ل) و العرض (ب) . متى المنطقة (أ ب) ويسمى أنه يتوسع إلى (أ * ب) ويتم حساب النتيجة وطباعتها.
يرجى الرجوع أنواع وحدات الماكرو في C لمزيد من الأمثلة والأنواع.
إدراج الملف
يسمح لك تضمين الملف بتضمين ملفات خارجية (مكتبات ملفات الرأس وما إلى ذلك) في البرنامج الحالي. ويتم ذلك عادة باستخدام #يشمل التوجيه الذي يمكن أن يتضمن كلا من ملفات النظام والملفات المعرفة من قبل المستخدم.
بناء الجملة
هناك طريقتان لتضمين ملفات الرأس.
#يشمل
#يشمل "اسم الملف"شار إلى السلسلة
ال '<' و ">" بين قوسين اطلب من المترجم البحث عن الملف في ملف الدليل القياسي بينما علامات الاقتباس المزدوجة ('') اطلب من المترجم البحث عن ملف الرأس في دليل الملف المصدر.
مثال:
C// Includes the standard I/O library #include int main() { printf('Hello World'); return 0; }
الإخراج
Hello World
التجميع الشرطي
التجميع الشرطي يسمح لك بتضمين أجزاء من الكود أو استبعادها وفقًا لشروط معينة. يعد هذا مفيدًا لإنشاء تعليمات برمجية خاصة بالنظام الأساسي أو لتصحيح الأخطاء. توجد توجيهات المعالج الشرطي التالية: #if #ifdef #ifndef else #elif و #endif
بناء الجملة
بناء الجملة العام للمعالجات الشرطية هو:
#لو
// بعض التعليمات البرمجية
#elif
// المزيد من التعليمات البرمجية
#آخر
// المزيد من التعليمات البرمجية
#endif
يتم استخدام التوجيه #endif لإغلاق توجيهات الفتح #if #ifdef و #ifndef.
مثال
C#include // Defining a macro for PI #define PI 3.14159 int main(){ // Check if PI is defined using #ifdef #ifdef PI printf('PI is definedn'); // If PI is not defined check if SQUARE is defined #elif defined(SQUARE) printf('Square is definedn'); // If neither PI nor SQUARE is defined trigger an error #else #error 'Neither PI nor SQUARE is defined' #endif // Check if SQUARE is not defined using #ifndef #ifndef SQUARE printf('Square is not defined'); // If SQUARE is defined print that it is defined #else printf('Square is defined'); #endif return 0; }
الإخراج
PI is defined Square is not defined
توضيح: يستخدم هذا الرمز توجيهات المعالج الشرطي ( #ifdef #elif و #ifndef ) للتحقق مما إذا كانت وحدات ماكرو معينة ( باي و مربع ) يتم تعريفها. منذ أن تم تعريف PI يطبع البرنامج " يتم تعريف PI 'ثم يتحقق مما إذا كان SQUARE لم يتم تعريفه ويطبع' لم يتم تعريف الساحة '.
توجيهات أخرى
بصرف النظر عن توجيهات المعالج الأولي الأساسية، توفر لغة C أيضًا توجيهات أخرى لإدارة سلوك المترجم وتصحيح الأخطاء.
#براغما:
يوفر تعليمات محددة للمترجم للتحكم في سلوكه. يتم استخدامه لتعطيل محاذاة مجموعة التحذيرات وما إلى ذلك.
بناء الجملة
#براغما التوجيه
أين هي إعدادات المتصفح
تمت مناقشة بعض توجيهات #pragma أدناه:
- #بدء العمل بالبراغما: تساعدنا هذه التوجيهات على تحديد الوظائف المطلوبة للتشغيل قبل بدء تشغيل البرنامج (قبل أن ينتقل عنصر التحكم إلى main()).
- #خروج براغما : تساعدنا هذه التوجيهات على تحديد الوظائف المطلوبة للتشغيل قبل خروج البرنامج مباشرة (قبل عودة عنصر التحكم من main() مباشرة).
مثال
C#include void func1(); void func2(); // specifying funct1 to execute at start #pragma startup func1 // specifying funct2 to execute before end #pragma exit func2 void func1() { printf('Inside func1()n'); } void func2() { printf('Inside func2()n'); } int main(){ void func1(); void func2(); printf('Inside main()n'); return 0; }
الإخراج
Inside main()
سينتج الكود أعلاه المخرجات كما هو مذكور أعلاه عند تشغيله على مترجمات دول مجلس التعاون الخليجي بينما كان الناتج المتوقع هو:
الناتج المتوقع
Inside func1() Inside main() Inside func2() يحدث هذا لأن دول مجلس التعاون الخليجي لا تدعم بدء التشغيل أو الخروج #pragma. ومع ذلك، يمكنك استخدام الكود أدناه للمخرجات المتوقعة على المترجمين في دول مجلس التعاون الخليجي.
C#include void func1(); void func2(); void __attribute__((constructor)) func1(); void __attribute__((destructor)) func2(); void func1() { printf('Inside func1()n'); } void func2() { printf('Inside func2()n'); } int main() { printf('Inside main()n'); return 0; }
الإخراج
Inside func1() Inside main() Inside func2()
في البرنامج أعلاه استخدمنا بعض جمل محددة بحيث يتم تنفيذ إحدى الوظائف قبل الوظيفة الرئيسية ويتم تنفيذ الأخرى بعد الوظيفة الرئيسية.
إنشاء اختبار