لغة سي و متحكماتمقالات

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]

Yahya Tawil

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

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني.

هذا الموقع يستخدم Akismet للحدّ من التعليقات المزعجة والغير مرغوبة. تعرّف على كيفية معالجة بيانات تعليقك.

زر الذهاب إلى الأعلى