English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
في هذا الدرس، سنقدم لك معالج البرمجة في C، وسنتعلم باستخدام #include، #define وتحليل الشروط المسبقة في أمثلة.
معالج البرمجة في Cليس جزءًا من معالج البرمجة، ولكن هو خطوة منفصلة في عملية البرمجة. باختصار، معالج البرمجة في C هو أداة استبدال النص فقط، التي ستشير إلى معالج البرمجة للقيام بما يلزم قبل البرمجة الفعلية. سنقوم بتسمية معالج البرمجة في C (C Preprocessor) بـ CPP.
جميع أوامر المعالج المسبق تبدأ بمعرف ( #( )). يجب أن يكون هذا المعرف أول رمز غير فارغ، من أجل تحسين القدرة على القراءة، يجب أن تبدأ أوامر المعالج المسبق من الصف الأول. يُظهر لنا ما يلي جميع الأوامر المهمة لمعالج المعالج المسبق:
الأمر | الوصف |
---|---|
#define | تعريف الماكرو |
#include | تضمين ملف مصدر |
#undef | إلغاء تعريف الماكرو المحدد |
#ifdef | إذا تم تعريف الماكرو، يتم العودة إلى الحقيقة |
#ifndef | إذا لم يتم تعريف الماكرو، يتم العودة إلى الحقيقة |
#if | إذا كانت الشروط المقدمة صحيحة، يتم تجميع الكود أدناه |
#else | بديل #if |
#elif | إذا كانت الشروط المقدمة سابقاً غير صحيحة، والشروط الحالية صحيحة، يتم تجميع الكود أدناه |
#endif | تنتهي من مكتبة تعديل شرطية #if……#else |
#error | عند مواجهة خطأ معياري، يتم عرض رسالة الخطأ. |
#pragma | استخدام طريقة معيارية، ننشر أوامر خاصة إلى معالج البرمجة |
تحليل المثال أدناه لفهم الأوامر المختلفة.
#define MAX_ARRAY_LENGTH 20
هذا الأمر يخبر CPP بتبديل كل MAX_ARRAY_LENGTH إلى 20. باستخدام #define تعريف القيم الثابتة لتحسين القدرة على القراءة.
#include <stdio.h> #include "myheader.h"
هذه الأوامر تخبر CPP للحصول علىالمكتبة النظاميةالحصول على stdio.h من الدليل الحالي، ويضيف النص إلى الملف المصدر الحالي. الخط التالي يخبر CPP للحصول على myheader.h، ويضيف محتوى إلى الملف المصدر الحالي.
#undef FILE_SIZE #define FILE_SIZE 42
تخبر هذه التعليمات CPP إلغاء تعريف FILE_SIZE المحدد مسبقًا، وتعريفه كـ 42.
#ifndef MESSAGE #define MESSAGE "You wish!" #endif
تخبر هذه التعليمات CPP إذا لم يتم تعريف MESSAGE، يتم تعريف MESSAGE.
#ifdef DEBUG /* Your debugging statements here */ #endif
تخبر هذه التعليمات CPP إذا كان DEBUG معرفًا، يتم تنفيذ التعليمات المعالجة. عند التجميع، إذا كنت قد نقلت إلى معالج GCC -DDEBUG مفتاح التشغيل، هذه التعليمات مفيدة جدًا. يحدد DEBUG، يمكنك تشغيل أو إيقاف التتبع في أي وقت خلال التجميع.
يعرف معيار C العديد من الماكرو. يمكنك استخدام هذه الماكرو في البرمجة، ولكن لا يمكنك تعديل الماكرو المحددة مسبقًا.
الماكرو | الوصف |
---|---|
__DATE__ | التاريخ الحالي، كمية نصية ثابتة تُعبر عنها بـ "MMM DD YYYY". |
__TIME__ | الوقت الحالي، كمية نصية ثابتة تُعبر عنها بـ "HH:MM:SS". |
__FILE__ | سيكون هذا يحتوي على اسم الملف الحالي، كمية نصية ثابتة. |
__LINE__ | سيكون هذا يحتوي على رقم السطر الحالي، كمية ثابتة عشرية. |
__STDC__ | عندما يتم تجميع الماكرو بمعيار ANSI، يتم تعريفه كـ 1. |
لنحاول الآن مثالًا تحتويًا على:
#include <stdio.h> main() { printf("الملف :%s\n", __FILE__); printf("التاريخ :%s\n", __DATE__); printf("الوقت :%s\n", __TIME__); printf("السطر :%d\n", __LINE__); printf("ANSI :%d\n", __STDC__); }
عندما يتم تجميع الكود (في ملف test.c عندما يتم تجميع وتنفيذ) ينتج النتيجة التالية:
الملف :test.c التاريخ :Jun 2 2012 الوقت :03:36:24 السطر :8 ANSI :1
يقدم معالج C التالي العمليات المساعدة لإنشاء الماكرو:
عميل التمديد الماكرو (\)
عادة ما يكتب الماكرو على سطر واحد. ولكن إذا كان الماكرو طويلاً غير قادر على احتواءه على سطر واحد، يتم استخدام عميل التمديد الماكرو (\). على سبيل المثال:
#define message_for(a, b) \" printf(#a " and " #b ": We love you!\n")
字符串常量化运算符(#)
في التعريف الماكرو، عند الحاجة إلى تحويل معامل الماكرو إلى متغير نصي ثابت، يتم استخدام عميل التبديل النصي الثابت (#). ويكون لديه هذا العميل معامل معين أو قائمة من المعاملات في الماكرو. على سبيل المثال:
#include <stdio.h> #define message_for(a, b) \" printf(#a " and " #b ": We love you!\n") int main(void) { message_for(Carole, Debra); return 0; }
عندما يتم ترميز وتشغيل الكود أعلاه، سيتم توليد النتيجة التالية:
Carole and Debra: We love you!
标记粘贴运算符(##)
宏定义内的标记粘贴运算符(##)会合并两个参数。它允许在宏定义中两个独立的标记被合并为一个标记。例如:
#include <stdio.h> #define tokenpaster(n) printf("token" #n " = %d", token##n) int main(void) { int token34 = 40; tokenpaster(34); return 0; }
عندما يتم ترميز وتشغيل الكود أعلاه، سيتم توليد النتيجة التالية:
token34 = 40
这是怎么发生的,因为这个示例会从编译器产生下列的实际输出:
printf("token34 = %d", token34);
这个示例演示了 token##n 会连接到 token34 中,在这里,我们使用了字符串常量化运算符(#)和标记粘贴运算符(##)。
defined() 运算符
预处理器 defined 运算符是用在常量表达式中的,用来确定一个标识符是否已经使用 #define 定义过。如果指定的标识符已定义,则值为真(非零)。如果指定的标识符未定义,则值为假(零)。下面的示例演示了 defined() 运算符的用法:
#include <stdio.h> #if !defined(MESSAGE) #define MESSAGE "You wish!" #endif int main(void) { printf("这是消息: %s\n", MESSAGE); return 0; }
عندما يتم ترميز وتشغيل الكود أعلاه، سيتم توليد النتيجة التالية:
这是消息: You wish!
CPP 一个强大的功能是可以使用参数化的宏来模拟函数。例如,下面的代码是计算一个数的平方:
int square(int x) { return x * x; }
我们可以使用宏重写上面的代码,如下:
#define square(x) ((x) * (x))
在使用带有参数的宏之前,必须使用 #define 指令定义。参数列表是括在圆括号内,且必须紧跟在宏名称的后边。宏名称和左圆括号之间不允许有空格。例如:
#include <stdio.h> #define MAX(x,y) ((x) > (y) ? (x) : (y)) int main(void) { printf("أكبر قيمة بين 10 و 20 هي %d\n", MAX(10, 20)); return 0; }
عندما يتم ترميز وتشغيل الكود أعلاه، سيتم توليد النتيجة التالية:
أكبر قيمة بين 10 و 20 هي 20