زبان برنامه نویسی سی/ماکروها
ماکروهای سراسری، کدهایی هستند که بین دو « _ » یعنی به شکل __CODE__ داخل متن برنامه نوشته میشوند تا مطابق با آنچه تشریح میشود، مقداری را بازگردانده که آنها را در ذیل مینویسیم:
__LINE__
این ماکرو شماره خطی را که در آن نوشته باشید به صورت مقدار عددی در مبنای ۱۰ (دهدهی) باز میگرداند
__FILE__
با این ماکرو، کامپایلر، نام فایلی که در هر حال حاضر در حال کامپایل آن است، باز میگرداند که خروجی به صورت یک رشته خواهد بود
__DATE__
با این ماکرو، کامپایلر، تاریخ کامپایل فایل متن شما را باز میگرداند که به صورت: سال (چهار رقمی) روز (دو رقمی) ماه (دو رقمی) میباشد
__TIME__
نمایش زمان کامپایل فایل از طریق این کد ماکرو به واسطه کامپایلر، فراهم میگردد که به صورت: ثانیه (دو رقمی) : دقیقه (دو رقمی) : ساعت (دو رقمی) میباشد
__STDC__
این ماکرو به عنوان خروجی باز میگرداند که آیا کامپایلر بر اساس استاندارد زبان C میباشد یا خیر و پاسخ به صورت 0 و 1 نمایش داده خواهد شد (0 یعنی خیر و 1 یعنی آری)
__STDC_HOSTED__
مقدار خروجی این ماکرو به شما خواهد گفت که آیا کامپایلر از کتابخانه استاندارد C پشتیبانی مینماید یا خیر و همانند ماکروی پیشین با 0 و 1 پاسخ میدهد (0 یعنی خیر و 1 یعنی آری)
__STDC_VERSION__
این ماکرو مقداری را به عنوان خروجی باز میگرداند که مقدار بازگردانده شده نمایش میدهد که کامپایلر با کدام استاندارد زبان C سازگار است. 199901L برای استاندارد سال ۹۹ (ISO/IEC 9899:1999) و 201112L برای استاندارد سال ۲۰۱۱ و 201710L برای استاندارد C18 که در اواخر سال ۲۰۱۷ به تصویب رسید و به عنوان سی ۱۸ شناخته میشود، میباشند
__func__
این ماکرو نام تابعی که در آن به کار رفته باشد را به عنوان خروجی، تحت یک رشته، باز میگرداند
__STDC_IEC_559__
این ماکرو مقدار 1 یا 0 را در ازای اینکه آیا تمام پردازشهای ریاضی بر روی اعداد اعشاری را با استاندارد IEC 60559 (مصوّب انستیتوی جهانی مهندسین برق و الکترونیک) انجام میشوند یا خیر باز میگرداند (1 یعنی آری و 0 یعنی خیر)
__STDC_IEC_559_COMPLEX__
این ماکرو همانند ماکروی قبلی است با این تفاوت که نشان میدهد تا تمام پردازشهای ریاضی بر روی اعداد مختلط با استاندارد IEC 60559 (مصوّب انستیتوی جهانی مهندسین برق و الکترونیک) انجام میشوند یا خیر (که مقدار 1 را در صورت مطابقت باز میگرداند و اگر مطابق با استاندارد نباشد، مقدار 0 را بازمیگرداند)
__STDC_ISO_10646__
این ماکرو مقداری را باز میگرداند که نشان میدهد کاراکترهای اضافهتر از اسکی یا همان ازکی ASCII را که در استاندارد ISO 10646 تعریف شدهاند و کامپایلر از آنها پشتیبانی میکند، متعلق به استاندارد کدام سال است. در گذشته، بسیاری از کامپایلرها آن را نادیده میگرفتند اما بعد از استاندارد C11 کامپایلرهای مطرح مثل کلنگ، جیسیسی و ویژوال استودیو سیپلاسپلاس، اجازه استفاده از کاراکترهای یونیکد را میدهند. این مقدار به صورت yyyymmL یعنی ابتدا سال (چهار رقم) و سپس ماه (دو رفم) و یک کاراکتر L در انتهای آن میباشد
__STDC_MB_MIGHT_NEQ_WC__
این ماکرو مقداری را باز میگرداند که نشان میدهد نوع داده کاراکتر در کامپایلر همان مقدار کاراکترهای wchar_t را (که در استانداردهای جدید تصویب شدند) دارد یا خیر؛ این مقدار یا 1 است که به معنای آری میباشد و یا 0 به معنی خیر
دقت کنید: مابقی ماکروهایی که در ذیل نوشته میشوند فقط در کامپایلرهای منطبق با C11 و C18 تعریف شدهاند
__STDC_LIB_EXT1__
ماکروی اختصاصی مایکروسافت که به اصرار این کمپانی به استاندارد C افزوده شد و برای چک کردن عدم تداخل مقدارهای داده شده به متغیرها با طیف قابل ذخیره در هر نوع از متغیر میباشد (Bound Checking) که بسیاری از کامپایلرها از آن پشتیبانی نمیکنند ولی ++Visual Studio C از مایکروسافت آن را به رسمیت میشناسد (در صورتی که مقدار 1 را باز گرداند یعنی کامپایلر پشتیبانی میکند و در صورتی که 0 را باز گرداند یعنی پشتیبانی نمیکند)
__STDC_WANT_LIB_EXT1__
در صورتی که شک داشتید کامپایلر شما از annex K (Bounds-checking interfaces) با ماکروی پیشین یعنی __STDC_LIB_EXT1__ استفاده میکند یا خیر و یا در Visual Studio خواستید آن را از کار بیاندازید ماکروی فعلی را با کمک دستور مستقیم پیش پردازنده define مقدار 0 بدهید (در مقابل ماکرو که آن را define میکنید مقدار 0 را بنویسید) تا احیاناً توابع از پیش تعریف شده آن با کدهای شما تداخل نیابند و اگر خواستید آن را فعال کنید به آن مقدار 1 بدهید (در صورتی که خواستید آن را از کار بیاندازید با دستور مستقیم پیشپردازنده define# ماکرو را بنویسید و در مقابل ماکرو مقدار 0 را بگذارید و هر وقت خواستید دوباره آن را فعال کنید تا ادامه متنمنبع برنامه Program's Source Code فعّال شود با دستور مستقیم پیشپردازنده define# مقدار 1 را در مقابل ماکرو بنویسید؛ رجوع شود به پیشپردازندههای تعریفی و شرطی)
__STDC_ANALYZABLE__
این ماکرو با باز گرداندن مقدار 0 نشان میدهد که کامپایلر از محدود کردن رفتارهای تعریفنشده، پشتیبانی نمیکند و با بازگرداندن مقدار 1 نشان میدهد که کامپایلر از این قابلیت پشتیبانی میکند. ضمن اینکه در صورت نوشته شدن آن در برنامه، پیش از خود متن منبع و پشتیبانی آن توسط کامپایلر، محدودیتها اعمال میگردند. در ادامه کتاب، رفتارهای تعریفنشده و ریسکپذیر را خواهید خواند، اما به صورت خلاصه، هر کد نوشته شدهای که مثلاً بخواهد با اشارهگر به یک داده از بینرفته یا اینکه اشارهگر با نوع داده اشارهشده به آن ناسازگار باشد، اشاره کند، یا پردازشی بر روی داده که منجر به سرریز شدن داده داخل حافظه شود و ... که در صورتی که این خطاها در برنامه وجود داشته باشند، جلوی کامپایل برنامه را میگیرد و به صورت تکمیلی (کاملتر از کامپایلرهای معمولی) خطا را در برنامه، در خروجی خط دستوری، نمایش میدهد
__STDC_NO_ATOMICS__
این ماکرو در صورتی که مقدار 1 را باز گرداند یعنی از نوع دادههای اتمی و فایل سرآیند stdatomic.h پشتیبانی نمیکند و در صورتی باز گرداندن 0 به شما میگوید که پشتیبانی میکند؛ ممکن است این ماکرو تعریف نشده باشد؛ در صورتی که کامپایلر با استاندارد C11 یا C18 مطابقت کند، یعنی از نوع دادههای اتمی پشتیبانی میکند
__STDC_NO_COMPLEX__
این ماکرو با بازگرداندن عدد 1 نشان میدهد که از نوع دادههای مختلط و فایل سرآیند stdcomplex.h پشتیبانی نمیکند و در صورت بازگرداندن 0 نشان میدهد که پشتیبانی میکند؛ در صورتی که کامپایلر با استاندارد C11 یا C18 مطابقت کند، یعنی از نوع دادههای مختلط پشتیبانی میکند
__STDC_NO_THREADS__
این ماکرو با باز گرداندن عدد 1 نشان میدهد که از برنامهنویسی برای ریسهها و فایل سرآیند stdthreads.h پشتیبانی نمیکند و در صورت بازگرداندن عدد 0 نشان میدهد که پشتیبانی میکند؛ در صورتی که کامپایلر با استاندارد C11 یا C18 مطابقت کند، یعنی از نوع دادهها و برنامهنویسی برای ریسهها پشتیبانی میکند
__STDC_NO_VLA__
این ماکرو با باز گرداندن عدد 1 نشان میدهد که از آرایههایی با اندیسهای نامعین و دادههایی که مقدار آرایههای با اندیس نامعین را دارند، پشتیبانی نمیکند و باز گرداندن عدد 0 نمایانگر پشتیبانی کامپایلر از این نوع دادهها میباشد؛ در صورتی که این ماکرو در کامپایلر شما تعریف نشده باشد و کامپایلر با استاندارد C11 یا C18 سازگاری داشته باشد، یعنی از نوع داده VLA به معنی آرایههایی با اندیسهای نامعین و دادههایی که شامل آنها هستند (Variable-length array) پشتیبانی میکند
__STDC_UTF_16__
این ماکرو با باز گرداندن مقدار 0 نشان میدهد که کامپایلر از انکدینگ/دکدینگ، یونیکد UTF-16 پشتیبانی نمیکند و در صورت بازگرداندن مقدار 1 نشان میدهد که پشتیبانی میکند
__STDC_UTF_32__
این ماکرو با بازگرداندن مقدار 0 نشان میدهد که کامپایلر از انکدینگ/دکدینگ، یونیکد UTF-32 پشتیبانی نمیکند و در صورت بازگرداندن مقدار 1 نشان میدهد که پشتیبانی میکند
استفاده :
لازم نیست فعلاً قطعه کد زیر را کاملاً درک کنید، به صورت خلاصه مینویسیم که: تابع کتابخانهای printf در فایل سرآیند stdio تعریف شده است که مقادیر دستور گرفته شده را در خروجی خطدستوری سیستمعامل و یا سیستم (در صورت برنامهنویسی سطح پائین) نمایش میدهد که با دستور مستقیم پیشپردازنده include فایل سرآیند مورد نظر، یعنی stdio را ابتدای برنامه و پیش از استفاده از تابع، ضمیمه نمودهایم تا آن را (تابع printf را) فراخوانی یا احضار کنیم تا مقدار بازگردانده شده توسط ماکروهای بالا را نمایش دهد:
#include<stdio.h>
int main(void)
{
printf("%d\n", __STDC_IEC_559__);
return 0;
}
این مثال ، مقدار بازگردانده شده توسط STDC_IEC_559 را به صورت خط دستوری پس از کامپایل و اجرای برنامه، نمایش خواهد داد. شما هر ماکرویی را که خواستید امتحان کنید که با استانداردهای C98 یا C99 یا C11 یا C18 و کامپایلر سازگار است یا خیر و یا مقدار ماکروهای دیگر را خواستید، جایگزین «STDC_IEC_559» در قطعه کد بالا کنید، قطعه کد را در یک فایل متنی با پسوند c. ذخیره کنید، پس از کامپایل و اجرای آن از طریق ترمینال Terminal، در سیستمعاملهای یونیکس و یا commander که همان فایل cmd.exe در ویندوز است، نتیجه خود را در خروجی خط دستوری، مشاهده کنید (برای سهولت در این کار، میتوانید از IDEها استفاده کنید و فایل را در یک پروژه خطدستوری CLI بسازید و سپس Compile و بعد Build و بعد Run را از منوی Build در Menu Bar برنامه IDE بزنید؛ در ادامه کتاب، نحوه کامپایل کردن را نیز نوشتهایم؛ اما میتوانید با مطالعه راهنمای پیادهساز خود و یا سرچ کردن در وب نحوه کامپایل را بیابید)