C preprocessor الجزء 3
سنتعرف في الجزء الثالث والأخير على استخدام C preprocessor في الترجمة الشرطية conditional compilation والتي تفيد في جعل الكود قابل لإعطاء بعض الشروط للمترجم كما سنرى. وسنختم هذا الجزء بمثال عملي حقيقي على استخدام الـ C preprocessor .
ملاحظة:الأمثلة الوارد في هذا الجزء مأخوذة من المصادر الموضوعة في النهاية.
الترجمة الشرطية conditional compilation
تستخدم الأوامر if, ifdef, ifndef, else, elif ,endif في الترجمة الشرطية.
1-#if … #endif
إن if و endif تحويان كود برمجي ينفذ عندما يكون الوسيط بعد if له قيمة غير صفرية، مثال:
#define DEBUG 1 #if DEBUG #include <debug.h> #endif
وليس بالضروري أن يكون الكود بين if و endif هو من أوامر C preprocessor إذا يمكن أن نكتب أي كود نريد. وبالتالي يمكن استخدام هذه الخاصية أيضاً في جعل الكود قابل لإعادة الاستخدام أو التخصيص عبر المطور.
2-#elif … #else
تستخدم else لتوجيه المترجم لكود آخر في حال عدم تحقق شرط if
#define DEBUG 1 #if DEBUG #include <debug.h> #endif
أما elif فهي تختلف عن else بوجود شرط تقوم بتفحصه، مثال:
#define STATE DEBUG #if STATE == DEBUG #include <debug.h> #elif STATE == TESTING #include <testing.h> #elif STATE == RELEASE #include <machine.h> #endif
3-#ifdef … #ifndef
يستخدم ifdef من أجل تضمين كود في حال التأكد من أن الوسيط معرف، أما ifndef فهي من أجل تضمين كود في حال أن الوسيط غير معرف. يجب الانتباه أننا هنا لا نتحدث عن وسيط له قيمة غير صفرية وإنما هل هو معرف أم لا.
#define DEBUG #ifdef DEBUG #include <debug.h> #endif #ifndef DEBUG #include <machine.h> #endif
يمكن استخدام الC preprocessor من أجل تمرير رسائل معينة لإظهارها أثناء الترجمة في حال حدوث شرط معين، مثال:
#if RUBY_VERSION == 190 # error 1.9.0 not supported #endif
ففي الكود السابق يقوم بتفحص رمز سابق (معرّف مسبقاً لدى المترجم) وفي حال لم يكن بقيمة معينة فإنه يظهر رسالة إلى المستخدم.
مثال عملي
في نهاية هذه السلسلة، نذكر مقطع من مكتبة لغة Arduino C والمبنية على لغة C أساساً. سنجد استخداماً مكثفاً للـ C preprocessor :
#ifndef Arduino_h #define Arduino_h #include "binary.h" #ifdef __cplusplus extern "C"{ #endif #define HIGH 0x1 #define LOW 0x0 #define INPUT 0x0 #define OUTPUT 0x1 #define true 0x1 #define false 0x0 #define PI 3.1415926535897932384626433832795 #define HALF_PI 1.5707963267948966192313216916398 #define TWO_PI 6.283185307179586476925286766559 #define DEG_TO_RAD 0.017453292519943295769236907684886 #define RAD_TO_DEG 57.295779513082320876798154814105 #define SERIAL 0x0 #define DISPLAY 0x1 #define LSBFIRST 0 #define MSBFIRST 1 #define CHANGE 1 #define FALLING 2 #define RISING 3 #if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) #define DEFAULT 0 #define EXTERNAL 1 #define INTERNAL 2 #else #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #define INTERNAL1V1 2 #define INTERNAL2V56 3 #else #define INTERNAL 3 #endif #define DEFAULT 1 #define EXTERNAL 0 #endif // undefine stdlib's abs if encountered #ifdef abs #undef abs #endif #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) #define abs(x) ((x)>0?(x):-(x)) #define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) #define radians(deg) ((deg)*DEG_TO_RAD) #define degrees(rad) ((rad)*RAD_TO_DEG) #define sq(x) ((x)*(x)) #define interrupts() sei() #define noInterrupts() cli() #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) #define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) ) #define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L ) #define lowByte(w) ((uint8_t) ((w) & 0xff)) #define highByte(w) ((uint8_t) ((w) >> 8)) #define bitRead(value, bit) (((value) >> (bit)) & 0x01) #define bitSet(value, bit) ((value) |= (1UL << (bit))) #define bitClear(value, bit) ((value) &= ~(1UL << (bit))) #define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
المراجع وروابط خارجية
http://www.mybitbox.com/2012/12/robust-c-code-part-3-wrapping-c/
http://www.mybitbox.com/2012/12/robust-c-code-part-2-advanced-c-preprecessor/
http://www.mybitbox.com/2012/11/robust-c-code-part-1-c-preprocessor/
http://www.cprogramming.com/tutorial/cpreprocessor.html
http://www2.hh.se/staff/vero/embeddedProgramming/lectures/printL2.pdf
http://www.phaedsys.com/principals/bytecraft/bytecraftdata/bcfirststeps.pdf
http://en.wikipedia.org/wiki/C_preprocessor
[related_posts_by_tax title=”مقالات مرتبطة” format=”thumbnails” image_size=”medium” taxonomies=”articles” posts_per_page=”3″ link_caption=1]