پیش‌پردازنده‌ها یا Preprocessor در ++C

پیش پردازنده‌ها دستوراتی هستند که به کامپایلر اعلام خواهند کرد که اطلاعات را پیش از آغاز عملیات کامپایل، چگونه پیش پردازش کنند.

همه دستورات پیش‌پردازنده با # آغاز می‌شوند. در هر خط، قبل از دستور پیش پردازنده  فقط استفاده از کارکترهای فضای خالی مجاز است. دستورات پیش‌پردازنده دستورات ++C به حساب نمی‌آیند، بنابراین پس از آنها سمی‌کالن (;) قرار نمی‌گیرد.

تاکنون دستور include# را در تمام مثال‌های خودمان دیده‌ایم. این ماکرو برای ضمیمه کردن یک هدرفایل در فایل سورس به کار می‌رود.

++C از چندین دستور پیش‌پردازنده پشتیبانی می‌کند.

این دستورات شامل «include ،#define ،#if ،#else ،#line#» و … هستند. اجازه دهید برخی از مهم‌ترین آنها را بررسی کنیم.

پیش‌پردازنده define#

این پیش‌پردازنده، ثابت‌های نمادین (symbolic constant) ایجاد می‌کند. این ثابت‌های نمادین ماکرو (macro) نامیده می‌شوند و شکل کلی زیر را دارند.

#define macro-name replacement-text 

پس از نوشتن این خط، تمام ماکروهای متعاقب پیش از کامپایل برنامه، با عبارت replacement-text جایگزین می‌شوند. به عنوان مثال:

#include <iostream>
using namespace std;

#define PI 3.14159

int main () {
   cout << "Value of PI :" << PI << endl; 

   return 0;
}

اکنون، با فرض داشتن سورس فایل، اجازه دهید کد را پیش‌پردازش کنیم. اجازه دهید کد را با گزینه E– کامپایل کرده و نتیجه را در test.p ذخیره کنیم. اکنون، اگر test.p را بررسی کنیم، در آن اطلاعات زیر را خواهیم یافت، و مشاهده خواهیم کرد که مقادیر پیش‌پردازنده جایگزین شده‌اند.

$gcc -E test.cpp > test.p

...
int main () {
   cout << "Value of PI :" << 3.14159 << endl; 
   return 0;
}

ماکروهای شبه تابع (Function-Like Macros)

با استفاده از دستور define# می‌توان ماکرویی تعریف کرد که از ورودی آرگومان دریافت خواهد کرد.

#include <iostream>
using namespace std;

#define MIN(a,b) (((a)<(b)) ? a : b)

int main () {
   int i, j;
   
   i = 100;
   j = 30;
   
   cout <<"The minimum is " << MIN(i, j) << endl;

   return 0;
}

اگر کد فوق را کامپایل و اجرا کنید، نتیجه زیر تولید خواهد شد.

The minimum is 30

کامپایل شرطی (Conditional Compilation)

دستوراتی وجود دارد که با استفاده از آنها، می‌توانید تنها بخش‌های خاصی از سورس کد برنامه‌تان را کامپایل کنید.

مطلب پیشنهادی:  کلاس‌ها و اشیا در ++C

ساختار پیش‌پردازنده شرطی (conditional preprocessor) شبیه ساختار دستور if می‌باشد. کد پیش‌پردازنده زیر را درنظر بگیرید.

#ifndef NULL
   #define NULL 0
#endif

می‌توان یک برنامه را با هدف دیباگ کردن کامپایل نمود. می‌توان با استفاده از یک دستور ماکرو، عملیات دیباگ را در برنامه فعال یا غیرفعال کرد.

#ifdef DEBUG
   cerr <<"Variable x = " << x << endl;
#endif

در صورتی که پیش از این ماکرو (یعنی ifdef DEBUG#)، ثابت نمادین DEBUG تعریف شده باشد، این ماکرو سبب می‌شود که دستور cerr در برنامه کامپایل گردد. با استفاده از دستور 0 if# ، می‌توان بخشی از برنامه را به صورت زیر کامنت کرد.

#if 0
   code prevented from compiling
#endif

مثال زیر را ملاحظه کنید.

#include <iostream>
using namespace std;
#define DEBUG

#define MIN(a,b) (((a)<(b)) ? a : b)

int main () {
   int i, j;
   
   i = 100;
   j = 30;

#ifdef DEBUG
   cerr <<"Trace: Inside main function" << endl;
#endif

#if 0
   /* This is commented part */
   cout << MKSTR(HELLO C++) << endl;
#endif

   cout <<"The minimum is " << MIN(i, j) << endl;

#ifdef DEBUG
   cerr <<"Trace: Coming out of main function" << endl;
#endif

   return 0;
}

با اجرای کد فوق، خروجی زیر حاصل می‌شود.

The minimum is 30
Trace: Inside main function
Trace: Coming out of main function

عملگرهای # و ##

عملگرهای پیش‌پردازنده # و ## در ++C و ANSI/ISO C موجود هستند. عملگر # سبب می‌شود تا یک توکن replacement-text به یک رشته محصور در کوتیشن تبدیل شود.

مطلب پیشنهادی:  اشاره‌گرها در ++C

ماکروی زیر را درنظر بگیرید.

#include <iostream>
using namespace std;

#define MKSTR( x ) #x

int main () {

   cout << MKSTR(HELLO C++) << endl;

   return 0;
}

با کامپایل این کد، نتیجه زیر به دست می‌آید.

HELLO C++

بیایید نحوه عملکرد این کد را بررسی کنیم. به سادگی می‌توان فهمید که پیش‌پردازنده ++C خط

cout << MKSTR(HELLO C++) << endl;

را به خط زیر تبدیل می‌کند.

cout << "HELLO C++" << endl;

عملگر ## برای چسباندن دو توکن به هم استفاده می‌شود. مثال زیر را مشاهده کنید.

#define CONCAT( x, y )  x ## y

هرجای برنامه که CONCAT ظاهر شود، آرگومان‌های آن بهم چسبیده و جایگرین ماکرو می‌شوند. برای مثال، (++CONCAT(HELLO, C با «++HELLO C» جایگزین می‌شود.

#include <iostream>
using namespace std;

#define concat(a, b) a ## b
int main() {
   int xy = 100;
   
   cout << concat(x, y);
   return 0;
}

اگر کد بالا اجرا شود، نتیجه زیر را خواهیم داشت.

100

اجازه دهید نحوه عملکرد برنامه را بررسی کنیم. به سادگی متوجه می‌شویم که پیش‌پردازنده ++C خط

cout << concat(x, y);

را به خط زیر تبدیل می‌کند.

cout << xy;

ماکروهای از پیش تعریف شده در ++C

 ++C تعدادی ماکروی از پیش تعریف شده فراهم آورده که در جدول زیر لیست شده‌اند.

ردیف

ماکرو و توضیح آن

1

__LINE__

این ماکرو شماره خطی از برنامه که در حال کامپایل شدن است را در خود نگه می‌دارد.

2

__FILE__

این ماکرو نام فایلی از برنامه که در حال کامپایل شدن است را در خود نگه می‌دارد.

3

__DATE__

این ماکرو حاوی رشته‌ای به فرم month/day/year است که بیانگر تاریخ ترجمه فایل سورس به فایل object می‌باشد.

4

__TIME__

این ماکرو حاوی رشته‌ای به فرم hour:minute:second است که بیانگر ساعت کامپایل برنامه می‌باشد.

مثالی از همه این ماکروها در زیر آمده است.

#include <iostream>
using namespace std;

int main () {
   cout << "Value of __LINE__ : " << __LINE__ << endl;
   cout << "Value of __FILE__ : " << __FILE__ << endl;
   cout << "Value of __DATE__ : " << __DATE__ << endl;
   cout << "Value of __TIME__ : " << __TIME__ << endl;

   return 0;
}

خروجی زیر از کد بالا حاصل شده است.

Value of __LINE__ : 6
Value of __FILE__ : test.cpp
Value of __DATE__ : Feb 28 2011
Value of __TIME__ : 18:52:48

منبع: ترجمه از سایت tutorialspoint.com

اگر این نوشته‌ برایتان مفید بود لطفا کامنت بنویسید.

مطالعه دیگر جلسات این آموزش<< جلسه قبلی                    جلسه بعدی >>
مطلب پیشنهادی:  تابع سازنده کپی در ++C

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

یک دیدگاه

  1. عالی بودش .