معرفی ماکروها و دستورات پیش‌پردازنده مرتبط در زبان 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

نام: *
پست الکترونیک (محرمانه):
تاریخ امروز با فرمت 14YYMMDD: *
پیام: *
• elham
۲۸ فروردین ۱۳۸۶، ساعت ۱۷:۴۷

salam t khaili ali bood bazam edameh bedid movafagh bashid

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

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

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

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

شهاب

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

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

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

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

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

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

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

روزبه .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

سلام

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