معرفی ماکروها و دستورات پیش‌پردازنده مرتبط در زبان C

معرفی ماکروها و دستورات پیش‌پردازنده مرتبط در زبان C

✓ مسعود اقدسی‌فام - ۱۷ آبان ۱۳۸۵ - آخرین به‌روزرسانی: ۱۸ مهر ۱۴۰۴

پیش‌پردازنده (Preprocessor) بخشی از فرایند کامپایل است که قبل از ترجمه‌ی واقعی برنامه اجرا می‌شود و کد را بر اساس نوع دستور بازنویسی کرده و آماده‌ی کامپایل می‌کند. مشهورترین دستور پیش‌پردازنده include است که ما برای اضافه کردن کتابخانه به کد استفاده می‌کنیم. ماکروها نیز یکی از امکانات زبان برنامه‌نویسی C (و صد البته ++C) هستند، که با استفاده از دستورات پیش‌پردازنده تعریف می‌شوند.

تعریف ماکرو

  [برگرد بالا]

ماکرو (macro) نامی‌برای یک رشته است. این رشته می‌تواند ترکیبی از حروف، ارقام، مقادیر ثابت، توابع و غیره باشد. دستور پیش‌پردازنده define# برای تعریف ماکرو استفاده می‌شود و ساختار کلی زیر را دارد.

#define macro-name character-sequence


در این مثال macro-name نام ماکرو و character-sequence عبارت معادل آن را مشخص می‌کند. پس از این تعریف، پیش‌پردازنده هرجا به عبارت macro-name بر خورد کند، آن را با chracter-sequence جایگزین می‌کند و پس از آن عملیات کامپایل انجام می‌شود. یک نکته‌ی مهم این است که تعریف ماکروها نیز مانند سایر دستورات پیش‌پردازنده به کاراکتر سمیکالن ختم نمی‌شوند.

روش اول تعریف ماکرو

  [برگرد بالا]

ساده‌ترین روش استفاده از ماکروها به این ترتیب است:

#define num 50

#define str "Programming"

این روش هیچ تفاوتی با متغیرهای ثابت (const) ندارد و می‌توان دو عبارت فوق را با عبارات زیر جایگزین کرد:

const int num = 50;

const char* str = "Programming";

روش دوم تعریف ماکرو

  [برگرد بالا]

روش دیگر استفاده از ماکرو (که البته خیلی کم کاربرد است) با یک مثال مشخص می‌شود:

#include<stdio.h>

#define BEGIN {

#define END }

#define INTEGER int

void main()

BEGIN

  INTEGER n = 5;

  printf ("%d", n);

END

این مثال تفاوت ماکرو با متغیر معمولی را نشان می‌دهد. در این کد پیش‌پردازنده هر جا به یکی از عبارات BEGIN ،END و INTEGER می‌رسد، آن را به ترتیب با {، } و int جایگزین می‌کند. این رویکرد کاربردهای خاص خود را دارد و به ندرت استفاده می‌شود.

روش سوم تعریف ماکرو

  [برگرد بالا]

اما روش سومی هم برای استفاده از ماکروها وجود دارد:

#include <stdio.h>

#define func(x) (x * x + x + 1 )

void main()

{

  int n;

  n = 2 * func(5);

  printf("%d", n);

}

کد بالا عدد 62 را چاپ می‌کند، که از محاسبه‌ی عبارت 2 * ( 5 * 5 + 5 + 1 ) به دست می‌آید. این روش را به نوعی می‌توان معادل تابع خطی در ++C دانست. اما باید توجه داشت که لزوما همان معنی را نمی‌دهد! کافی است تعریف ماکرو را به صورت زیر تغییر دهید:

#define func(x) x * x + x + 1

برنامه‌ی جدید خروجی 56 را تولید می‌کند. چرا که کل ماکرو در عبارت محاسباتی جایگزین می‌شود و تقدم ضرب دو به پنج بیشتر از جمع‌های داخل ماکرو است.

نکته‌ی مهم دیگر این است که این روش تعریف ماکرو باعث می‌شود که شما بتوانید از سربارگذاری توابع در C (البته به صورت خفیف!) استفاده کنید!

#include <stdio.h>

#define func(x) (x * x + x + 2)

void main()

{

  int i = func(5);

  float f = func(2.5);

  char c = func(8);

  printf("%d , %f , %c", i, f, c);

}

این برنامه خروجی زیر را تولید می‌کند:

32 , 10.75 , J

در واقع سه خط اول تابع اصلی به صورت زیر تفسیر می‌شوند:

int i = (5 * 5 + 5 + 2);       // i = 32

float f = (2.5 * 2.5 + 2.5 + 2);     // f = 10.75

char c = (8 * 8 + 8 + 2);       // c = 74  or  c = 'J'

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

دستور پیش‌پردازنده undef

  [برگرد بالا]

از دستور پیش‌پردازنده‌ی undef برای لغو تعریف ماکرو استفاده می‌شود و در واقع نقطه‌ی مقابل دستور define است.

#undef macro-name

خط بالا ماکروی macro-name را حذف و بی‌اثر می‌کند.

دستورات پیش‌پردازنده‌ی کنترلی

  [برگرد بالا]

منظور از دستورات پیش‌پردازنده‌ی شرطی را با چند مثال بررسی می‌کنیم.

#ifdef macro-name

    statements;

#endif

بر اساس کد بالا، اگر ماکروی macro-name تعریف شده باشد، عبارات داخل بلوک اجرا می‌شوند.

#ifndef macro-name

    statements;

#endif

در این کد اگر ماکروی macro-name تعریف نشده باشد، عبارات داخل بلوک اجرا می‌شوند.

#ifndef MATH_UTILS_H

#define MATH_UTILS_H

int add(int a, int b);

int subtract(int a, int b);

#endif

اگر یک فایل هدر زبان C به صورت بالا تعریف شود، حتی اگر چندین بار include شود، توابع add و subtract تنها یک بار به کدها اضافه می‌شوند.

#ifdef _WIN32

    buffer_size = 4096;

#elif defined(__linux__)

    buffer_size = 8192;

#elif defined(__APPLE__)

    buffer_size = 16384;

#else

    buffer_size = 1024;

#endif

پیش‌پردازنده‌ی زبان C (و ++C) تعدادی ماکرو از پیش تعریف‌شده (Predefined Macros) دارد که توسط خود کامپایلر تعریف می‌شوند و بسته به سیستم‌عامل یا محیط کامپایل مقداردهی می‌گردند. یکی از کاربردهای مهم این ماکروها، نوشتن کدهای چندسکویی (Cross-platform) است؛ یعنی کدهایی که روی چند سیستم‌عامل مختلف قابل کامپایل و اجرا باشند. در این مثال، فقط یکی از ماکروهای _WIN32، __linux__ و __APPLE__ توسط کامپایلرها و بسته به اینکه که در چه سکویی کامپایل می‌شود، تعریف شده‌اند و مقدار متغیر buffer_size متناسب با سیستم عامل تغییر می‌کند.


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


تا کنون ۰ امتیاز ثبت شده
نوشته لایک نداشت؟
 
به اشتراک گذاری نوشته

algs.ir/q6vrmr

اشتراک‌گذاری در LinkedIn     اشتراک‌گذاری در Twitter     ارسال با Telegram

نام: *  
پست الکترونیک (محرمانه):
پیام: *  
•  آرزو
۱۸ آبان ۱۳۸۵، ساعت ۲۰:۳۵

سلام

خوب دیگه به ما سر نمی زنین.............

• hamed
۱۹ آبان ۱۳۸۵، ساعت ۰۷:۴۴

salam rahandaziye mojadade vebsayteto behet tabrik migham ama oon kodi ke gharar bood behem bedi chi shod?

• میلاد - ریاضیات زیباست
۲۰ آبان ۱۳۸۵، ساعت ۰۱:۴۹

سلام آقا مسعود

چه عجب بالاخره ما تونستیم وارد وبلاگ شما بشیم و page can not displayed نداد!!!

آقا شما دیگه الان باید خودت یه پا server و ISP باشی...

البته می دونم از جهت افتخار دادن به این ISPها است که اومدی ازشون فضا گرفتی. نه؟

• میلاد - ریاضیات زیباست
۲۰ آبان ۱۳۸۵، ساعت ۰۱:۵۰

آقا یه سوال. کلا این واژه ماکرو از لحاظ فنی چه معنایی داره؟

آخه توی Microsoft Word هم ماکرو داریم!!

مسعود اقدسی‌فام
۲۰ آبان ۱۳۸۵، ساعت ۰۴:۲۲

از لطف دوستان ممنونم.

میلاد خان عزیز

سایت من حدود دو هفته از رده خارج شده بود. مجبور شدم میزبان رو عوض کنم و ... به همین خاطر سرم وحشتناک شلوغ بود.

در مورد ماکرو هم باید بگم حق با شماست. ماکروی MS Office Word همون مفهوم ماکروی C رو داره. اونجا هم ماکرو یک سری عملیات مشخص شده توسط کاربر رو به صورت مرتب و پشت سر هم انجام می ده. دقیقا مفهوم ماکروی C رو داره. اگه با ماکروی Word و ماکروی C همزمان کار کنید متوجه منظورم می شید.

• الفا
۲۰ آبان ۱۳۸۵، ساعت ۰۷:۱۲

سلام خسته نباشید من یکم اشکال تو برنامه نویسی دارم که اگه کمکم کنید ممنون می شم قربان شما

اگه منو راهنمایی کنید واقعا کمک بزرگی در حقم کردید

• روزبه
۲۰ آبان ۱۳۸۵، ساعت ۱۴:۳۱

سلام مسعود جان .

از اینکه دوباره برگشتی و به ما سری زدی متشکرم .

من لوگوی شما را در بلاگم گذاشتم .

به امید همکاری بیشتر در آینده موفق باشی .

روزبه .

• حسین
۲۲ آبان ۱۳۸۵، ساعت ۱۲:۴۳

ممنون از مطالب جالب و مفیدت

• شهاب الدین مختاری
۲۳ آبان ۱۳۸۵، ساعت ۰۳:۰۳

سلام آقا مسعود

خیلی جالب بود....مرسی :)

اینطوری که داری سایتتو گسترش میدی فکر کنم آخرش یه سی ام اس ازش در بیاد :) موفق باشی.

شهاب

• elham
۲۸ فروردین ۱۳۸۶، ساعت ۱۷:۴۷

salam t khaili ali bood bazam edameh bedid movafagh bashid