با سلام خدمت تمامی دوستان عزیز سایت پی وی لرن .و کاربرانی که دوره کامل آموزش زبان C را دنبال می کنند. و کاربرانی که با سری آموزش های زبان C همراهمون هستند. به توابع I / O در C و کار با فایل ها در C رو جلسه قبل پرداختیم. در این جلسه قصدداریم پیش پردازنده در زبان C و ماکروهای از پیش تعریف شده در C و عملگرهای پیش پردازنده و چند مثال رو مورد بحث قرار می دهیم. امیدوارم نهایت استفاده رو ببرید.
پیش پردازنده در زبان C جزء کامپایلر نیست، بلکه یک گام جداگانه در فرآیند کامپایل است. به طور ساده، یک پیش پردازنده C فقط یک ابزار جایگزینی متن است و دستور کامپایلر را قبل از کامپایل برنامه انجام می دهد.CPP مخفف C Preprocessor می باشد.
تمام دستورات پیش پردازنده در زبان C با یک نماد (#) آغاز می شود. این اولین کاراکتر غیرتهی باشد و برای خوانایی، دستورالعمل پیش پردازنده باید در ستون اول شروع شود. بخش زیر تمام دستورالعمل های پیش پردازنده مهم را فهرست می کند.با هم می بینیم :
ردیف | دستورالعمل و توضیحات |
۱ | define# یک ماکرو پیش پردازنده را جایگزین می کند. |
۲ | include# یک فایل هدر را به برنامه اضافه می کند. |
۳ | undef# ماکرو تعریف شده توسط دستور #define را حذف می کند. |
۴ | ifdef# اگر این ماکرو تعریف شده باشد، true باز می گرداند. |
۵ | ifndef# اگر این ماکرو تعریف نشده باشد، true باز می گرداند. |
۶ | if# دستور شرطی زمان کامپایل است. |
۷ | else# جایگزینی برای #if در صورتی که شرط بررسی شده درست نباشد. |
۸ | elif# #if و #else در یک دستور. |
۹ | endif# بخش شرطی پیش پردازنده را خاتمه می دهد. |
error# پیام خطا را در stderr تنظیم می کند. | |
pragma# با استفاده از یک روش استاندارد، دستورالعمل های خاصی را برای کامپایلر انجام خواهد داد. |
برای درک بهتر موضوع پیش پردازنده، مثال های زیر را بررسی کنید.
1 | #define MAX_ARRAY_LENGTH 20 |
در دستور بالا CPP برای جایگزینی MAX_ARRAY_LENGTH با مقدار ۲۰ استفاده می شود. یعنی هر کجایی از برنامه که MAX_ARRAY_LENGTH را استفاده کنید، هنگام کامپایل با ۲۰ جایگزین می شود.
define# را برای ثابت ها استفاده کنید تا خوانایی افزایش یابد.
1 2 | #include <stdio.h> #include "myheader.h" |
1 2 | #undef FILE_SIZE #define FILE_SIZE 42 |
1 2 3 | #ifndef MESSAGE #define MESSAGE "You wish!" #endif |
1 2 3 | #ifdef DEBUG /* Your debugging statements here */ #endif |
ردیف | ماکرو و توضیحات |
۱ | __DATE__ تاریخ جاری در فرمت “MMM DD YYYY” را در خود ذخیره می کند. |
۲ | __TIME__ زمان جاری در فرمت “HH: MM: SS” را در خود ذخیره می کند. |
۳ | __FILE__ نام فایل جاری را به صورت رشته در خود ذخیره می کند. |
۴ | __LINE__ شماره خط جاری را به صورت یک عدد دسیمال در خود ذخیره می کند. |
۵ | __STDC__ اگر عمل کامپایل بر اساس استاندارد ANSI صورت گیرد، مقدر یک را در خود ذخیره می کند. |
بیایید مثال زیر را امتحان کنیم .
1 2 3 4 5 6 7 8 9 | int main() { printf("File :%s\n", __FILE__ ); printf("Date :%s\n", __DATE__ ); printf("Time :%s\n", __TIME__ ); printf("Line :%d\n", __LINE__ ); printf("ANSI :%d\n", __STDC__ ); } |
هنگامی که کد بالا در فایل test.c کامپایل شده و اجرا می شود، نتیجه ی زیر را تولید می کند:
1 2 3 4 5 | File :test.c Date :Jun 2 2012 Time :03:36:24 Line :8 ANSI :1 |
زبان C برای ایجاد ماکروهایی با قابلیت بیشتر، عملگرهای زیر را ارائه می کند.
یک ماکرو معمولا در یک خط نوشته می شود، اما ممکن است گاهی اوقات ماکرو ما طولانی شود. در این مواقع می توان از عملگر (\) استفاده کرد. مانند نمونه زیر :
1 2 | #define message_for(a, b) \ printf(#a " and " #b ": We love you!\n") |
عملگر stringize یا number-sign، هنگامی که در تعریف ماکرو استفاده می شود، یک پارامتر ماکرو را به یک رشته ثابت تبدیل می کند. این عملگر ممکن است فقط در یک ماکرویی که آرگومان ثابتی یا لیست پارامتر دارد استفاده شود. به عنوان مثال :
1 2 3 4 5 6 7 8 9 | #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; } |
هنگامی که کد بالا کامپایل شده و اجرا می شود، نتیجه ی زیر را تولید می کند:
1 | Carole and Debra: We love you! |
عملگر(##) token-pasting در یک تعریف، ترکیبی از دو آرگومان است. این عملگر دو token جدا را به یک token واحد تبدیل می کند. به مثال زیر دقت کنید:
1 2 3 4 5 6 7 8 9 | #include <stdio.h> #define tokenpaster(n) printf ("token" #n " = %d", token##n) int main(void) { int token34 = 40; tokenpaster(34); return 0; } |
هنگامی که کد بالا کامپایل شده و اجرا می شود، نتیجه ی زیر را تولید می کند:
1 | token34 = 40 |
خروجی واقعی پیش پردازنده به صورت زیر است:
1 | printf ("token34 = %d", token34); |
این مثال نشان می دهد تلفیق token##n به token34 و در اینجا از هر دو stringize و token-paste استفاده کرده ایم.
عملگر پیش پردازنده defined در عبارات ثابت برای تعیین اینکه آیا یک شناسه با استفاده از #define تعریف شده است یا نه استفاده می شود.
اگر تعریف شده باشد، مقدار غیر صفر (true) باز می گرداند و اگر تعریف نشده باشد، مقدار صفر (false) باز می گرداند.به مثال زیر نحوه که استفاده از این عملگر است دقت کنید.
1 2 3 4 5 6 7 8 9 10 | #include <stdio.h> #if !defined (MESSAGE) #define MESSAGE "You wish!" #endif int main(void) { printf("Here is the message: %s\n", MESSAGE); return 0; } |
هنگامی که کد بالا کامپایل شده و اجرا می شود ، نتیجه ی زیر را تولید می کند:
1 | Here is the message: You wish! |
یکی از قابلیت های قدرتمند CPP توانایی شبیه سازی توابع با استفاده از ماکروهای parameterized است. به عنوان مثال، ما ممکن است برخی از کد را به مربع یک عدد به صورت زیر داشته باشیم .
به مثال توجه کنید:
1 2 3 | int square(int x) { return x * x; } |
ما می توانیم کد بالا را با استفاده از یک ماکرو به صورت زیر بازنویسی کنیم .
1 | #define square(x) ((x) * (x)) |
ماکروهای پارامتریک باید قبل از استفاده شدن، توسط دستور #define تعریف شوند. لیست پارامترها در داخل پرانتز قرار دارد و باید بلافاصله از نام ماکرو استفاده شود و نباید بین نام ماکرو و پرانتزها فاصله باشد. فضاهای بین نام ماکرو و پرانتز باز مجاز نیستند. مثلا:
1 2 3 4 5 6 7 8 | #include <stdio.h> #define MAX(x,y) ((x) > (y) ? (x) : (y)) int main(void) { printf("Max between 20 and 10 is %d\n", MAX(10, 20)); return 0; } |
هنگامی که کد بالا کامپایل شده و اجرا می شود، نتیجه ی زیر را تولید می کند:
1 | Max between 20 and 10 is 20 |
این جلسه پیش پردازنده در زبان C رو داشتیم ،در ادامه ماکروهای از پیش تعریف شده در C و انواع عملگرها ی پیش پردازنده و چند مثال رو با هم بررسی کردیم. در جلسه بعد فایل های header در زبان C رو مشاهده خواهیم کرد. همراهمون باشید .