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

در علوم رایانه، پیش‌پردازنده، برنامه‌ای را گویند که با پردازش داده‌های ورودی، دادهٔ خروجی‌ای تولید می‌کند که به عنوان ورودی برنامه دیگری مورد استفاده قرار می‌گیرد. خروجی پیش‌پردازنده را اصطلاحاً فرم پیش‌پردازش‌شده داده ورودی، که غالباً به وسیله یک برنامه ثانویه مانند همگردان مورد استفاده قرار می‌گیرد، می‌گویند.
پیش‌پردازنده‌ها بسته به طبیعتشان ممکن است فقط پردازش‌های ساده‌ای از قبیل جابه‌جائی متنی یا بسط ماکروئی روی داده ورودی انجام دهند، در عین حال، برخی از پیش‌پردازنده‌ها به اندازه یک زبان برنامه‌نویسی بالغ قدرتمند هستند.
یک نمونه رایج از برنامه‌نویسی، پیش‌پردازشی است که در پردازشگرهای متنی همگردان‌ها بر روی کد مبدأ انجام می‌گیرد و خروجی آن به پردازشگر نحوی تحویل می‌شود. در برخی زبان‌های برنامه‌نویسی (همچون C)، پیش‌پردازش یک فاز مستقل از فرایند ترجمه می‌باشد.

پیش‌پردازنده‌های لغوی

پیش‌پردازنده‌های لغوی، سطح‌پائین‌ترین پیش‌پردازنده‌ها هستند، زیرا فقط به تحلیل لغوی احتیاج دارند، یعنی مستقیماً روی کدمبداء کار می‌کنند.

راهنمای پیش‌پردازنده

راهنما، دستورالعملی به همگردان زبان در مورد چگونگی همگردانی برنامه می‌باشد. برنامه‌نویس به جای تولید کد، از راهنماها برای تعیین چگونگی یا حتی به وقوع پیوستن همگردانی کد مبدأ بهره می‌جوید. راهنماها در بسیاری از زبان‌های برنامه‌نویسی نسبتاً سطح پائین، چون C/C++‎ و اسمبلی مورد استفاده قرار می‌گیرند. در زبان‌های اسمبلی، راهنماها عموماً مشخص‌کننده پایگاه(Platform) مقصد و موارد مشابه می‌باشند. در C/C++‎ از راهنماها به جهت مقاصدی از قبیل همگردانی شرطی، ماکروها و شمول مورد استفاده قرارمی‌گیرند. باید توجه داشت که راهنماهای پیش‌پردازنده، به مانند دستورهایی هستند که به پیش‌پردازنده داده می‌شوند و بنابراین از قواعد زبان پیروی نمی‌کنند. یعنی این راهنماها قواعد املائی و نحوی خاص خود را دارند.

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

رایج‌ترین پیش‌پردازنده، پیش‌پردازنده C می‌باشد، که به صورت فراگیری در C و فرزند آن C++‎، استفاده می‌شود. از این پیش‌پردازنده به منظور استفاده از خدمات معمول پیش‌پردازنده‌ای استفاده می‌شود. این پیش‌پردازنده قادر به انجام اعمال اولیه‌ای از قبیل همگردانی شرطی، جا دادن فایل در کد منبع، تعیین پیغام خطاهای زمان همگردانی و اعمال قواعد مخصوص ماشین مقصد به بخش‌های کد نهائی می‌باشد.

پیش‌پردازنده تعریف، ‎#define

با استفاده از این راهنما می‌توان نامی را به یک ثابت در برنامه اختصاص داد. این راهنمای پیش‌پردازنده با دو نوع نحو زیر نوشته می‌شود. توجه داشته باشید که هر ‎#define در یک خط می‌باشد، بر ای نوشتن راهنمای پیش پردازنده در چندین خط از نویسه \ در پایان هر خط استفاده می‌شود:
#define identifier token-stringopt#define identifier( identifier(opt), ... , identifier(opt) ) token-stringopt
راهنمای ‎#define کلیه identifierهای بعد از خود را با token-string جابه‌جا می‌کند. هر identifier تنها زمانی جابه‌جا می‌شود که توسط تحلیل‌گر لغوی به عنوان یک توکن شناسائی شود. به عنوان مثال اگر identifier در یک قطعه توضیح کد (comment) ظاهر شود، جابه‌جائی صورت نمی‌پذیرد.
اگر قسمت token-string در راهنمای ‎#define وجود نداشته باشد، کلیه identifierهای یافت شده بعدی، حذف می‌شوند.
آرگمان token-string در راهنمای پیش‌پردازنده ‎#define، متشکل از یک سری توکن، از قبیل کلمات کلیدی، ثابت‌ها، یا دستورات کامل، می‌باشد. فضای سفیدی که در این راهنما identifier را از token-string جدا می‌کند، با هر طولی که باشد، جزء token-string به حساب نمی‌آید و در متن جایگزین نمی‌شود.
نوع دوم نحو این دستور امکان نوشتن ماکروهائی را در اختیار برنامه‌نویس قرار می‌دهد که دارای آرگمان‌هائی چون آرگمان‌های تابع باشند. این نوع املاء، لیستی از پارامترهای دلخواه، که باید در داخل پرانتز باشند، را به عنوان آرگومان می‌پذیرد. هر رخداد (identifier(arg-1, … , arg-n، پس از تعریف اولیه، با نسخه‌ای از token-string جای‌گذاری می‌شود که پارامترهای آن با آرگومان‌های پاس شده جابه‌جا شده‌است.
پارامترها در لیستشان به‌وسیله نویسه، از یکدیگر جدا می‌شوند. هر پارامتر باید نامی یکتا در لیست پارامترها داشته‌باشد. هیچ فضائی نباید بین نام ماکرو (identifier) و پرانتز وجود داشته باشد.
در صورتی که از نحو دوم استفاده شود، رخداد هر identifier در متن را یک فراخوانی ماکرو می‌نامند. در زیر چند مثال از تعریف ماکرو آورده شده‌است.
// Macro to define cursor lines#define CURSOR(top, bottom) (((top) << 8) | (bottom))// Macro to get a random integer// with a specified range#define getrandom(min, max) \    ((rand()%(int)(((max) + 1)-(min)))+ (min))// Macro to get maximum of to integers#define MAX(a, b) a>b?a:b
اگر نام ماکروئی که تعریف شده‌است، در token-string تکرار شود، نام تکرار شده، بسط نمی‌یابد (حتی اگر این تکرار بر اثر بسط ماکروی دیگری باشد). هر ماکرو فقط یک بار می‌تواند تعریف شود. تعریف چندباره یک ماکرو منجر به بروز خطا می‌شود، مگر آن‌که همه تعاریف کاملاً یکسان باشند.
معمولاً برای تعریف ماکروها از الگوی زیر استفاده می‌شود:
#defineMACRO_NAME(ARGUMENTS) do { \
        Statement 1;               \
            .                      \
            .                      \
            .                      \
        Statement n;               \
                                 } while(false)
مزیت این کار در آن است که اولاً کلیه متغیرهای محلی تعریف شده در این ماکرو یک برد محدود به خود ماکرو دارند و از این جهت باعث ایجاد خطای زمان کامپایل نمی‌شوند. همچنین دستور do-while()‎ دستوری است که نیازمند یک؛ در انتهای دستور است و بنابراین کاربر ماکرو با قرار دادن؛ در انتهای فراخوانی ماکرو متوجه تفاوت آن با تابع معمولی نمی‌شود.

پیش پردازنده ضد تعریف

دستور ‎#undef تعریف شده باشد، تعریف نشده می‌کند.
#undef identifier
راهنمای پیش‌پردازنده ‎#undef، تعریف فعلی identifier را بی‌اثر می‌کند. در نتیجه پیش‌پردازنده رخدادهای بعدی identifier را در نظر نمی‌گیرد. برای ضد تعریف کردن یک ماکرو که قبلاً تعریف شده‌است، نیازی به نوشتن پارامترها نیست و نوشتن نام ماکرو کفایت می‌کند.
می‌توان در این راهنما از identifierای استفاده کرد که قبلاً توسط راهنمای ‎#define تعریف نشده باشد. با این کار مطمئن می‌شویم که یک identifier حتماً تعریف نشده‌است.
از این راهنما، به همراه راهنمای ‎#define، به صورت یک جفت، برای مشخص کردن یک ناحیه در کد که یک identifier، یک معنی خاص دارد استفاده می‌شود. به عنوان مثال ممکن است تابعی با توجه به شاخصه‌های محیطی یک ثابت تعریف کند که در سایر بخش‌های کد تأثیری نداشته باشد. همچنین از این راهنما به همراه راهنماهای شرطی برای همگردانی شرطی استفاده می‌شود.
در مثال زیر، راهنمای پیش‌پردازنده ‎#undef تعریف یک ثابت و یک ماکرو را بی‌اثر می‌کند.
#define PE 3.1415#define MAX(a, b) a>b?a:b...#undef PE#undef MAX
توجه داشته باشید که بسط ماکرو در این راهنمای ریزپردازنده انجام نمی‌پذیرد. به عنوان مثال دستور زیر فقط تعریف B را بی‌اثر می‌کند و تأثیری در تعریف شاخص A ندارد.
#define A 10#define B A...#undef  B

راهنماهای شرطی تعریف، ifdef, ifndef

این راهنماها هم‌ارز راهنمای ‎#if هستند، در صورتی که به همراه عملگر define به کار رفته باشد.
#ifdef identifier#ifndef identifier// equivalent to#if defined identifier#if !defined identifier

راهنمای پیام خطا، ‎#error

این راهنما باعث ایجاد خطای زمان همگردانی می‌شود و غالباً به همراه راهنماهای شرطی به‌کار می‌رود. یک رشته از توکن‌ها در مقابل این راهنما قرار می‌گیرد که عیناً به عنوان پیغام خطا توسط همگردان بازگردانده می‌شود و عمل بسط ماکرو در آن صورت نمی‌گیرد.
#if !defined(__cplusplus)#error C++ compiler required.#endif
هم‌زمان با رسیدن به راهنمای ‎#error، همگردان کار خود را متوقف کرده، پیام خطای مربوطه را برمی‌گرداند.

راهنمای تغییر خط و فایل، ‎#line

این راهنما باعث تغییر نام فایل و شماره خط فعلی، ذخیره شده به صورت داخلی، در همگردان می‌شود.
#line digit-sequence["filename"]
همگردان در زمان مواجه شدن با خطا از نام فایل و شماره خطی که به صورت داخلی ذخیره کرده‌است برای اشاره کردن به محل رخداد خطا استفاده می‌کند. غالباً شماره خط به خط فعلی که در حال همگردان‌شدن می‌باشد اشاره می‌کند و با پردازش هر خط یک واحد افزایش می‌یابد، همچنین نام فایل به فایلی که در حال پردازش همگردان است اشاره می‌کند.
در این راهنما digital-sequence می‌تواند هر رشته رقمی که یک ثابت صحیح بسازد باشد. همچنین می‌توان در این‌جا از بسط ماکروها، به شرطی که نتیجه حاصله املای درستی داشته باشد، استفاده‌کرد.
مترجم، با استفاده از مقادیر داخلی نام فایل و شماره خط، مقدار ماکروهای از پیش تعریف شده __FILE__ و __LINE__ را تعیین می‌کند. با استفاده از این ماکروهای از پیش تعریف شده می‌توان پیام‌های خطای مشروحتری تولید کرد.

راهنمای #pragma

هر پیاده‌سازی از C/C++‎، ویژگی‌های منحصر به فرد مخصوص به ماشین میزبان یا سیستم‌عامل خود دارد. راهنمای پیش‌پردازنده ‎#pragma به هر همگردان این امکان را می‌دهد تا ویژگی‌های منحصر به فرد خود را در کنار حفظ سازگاری با تعریف استاندارد C/C++‎، پیاده‌سازی کند. ‎#pragma معمولاً مخصوص به ماشین و سیستم‌عامل مشخص است و غالباً در هر همگردان متفاوت می‌باشد. فرم کلی این راهنما به صورت زیر می‌باشد:
#pragma token-string