زبان برنامه نویسی سی/ماکروها

ویکی‎کتاب، کتابخانهٔ آزاد
پرش به ناوبری پرش به جستجو
Gnome-go-last.svg Gnome-go-first.svg

ماکروهای سراسری کدهایی هستند که بین دو « _ » یعنی به شکل __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 بزنید ؛ در ادامه کتاب ، نحوه کامپایل کردن را نیز نوشته‌ایم ؛ اما می‌توانید با مطالعه راهنمای پیاده‌ساز خود و یا سرچ کردن در وب نحوه کامپایل را بیابید )