سؤال

وقد كتبت القليل من ج, وأنا يمكن قراءتها جيدا بما فيه الكفاية للحصول على فكرة عامة عن ما تفعله ، ولكن في كل مرة كنت قد واجهت ماكرو وقد القيت لي تماما.أنا في نهاية المطاف الحاجة إلى تذكر ما الماكرو هو البديل في رأسي وأنا أقرأ.تلك التي كنت قد واجهت التي كانت بديهية وسهلة الفهم دائما مثل ميني وظائف, لذلك أنا دائما أتساءل لماذا لم تكن مجرد وظائف.

لا أستطيع فهم بحاجة إلى تحديد بناء مختلف أنواع التصحيح أو عبر منصة يبني في المعالج ولكن القدرة على تحديد التعسفي بدائل يبدو أن تكون مفيدة فقط الى لغة صعبة حتى أكثر من الصعب أن نفهم.

لماذا كان مثل هذا المجمع المعالج قدم ج?و هل لديها مثال على استخدام هذا يجعلني أفهم لماذا لا يزال يبدو أن تستخدم لأغراض أخرى غير بسيطة إذا #تصحيح نمط المشروط مصنفات?

تحرير:

بعد قراءة عدد من الإجابات ما زلت فقط لا تحصل عليه.الجواب الأكثر شيوعا هي مضمنة رمز.إذا كانت مضمنة الكلمة لا تفعل ذلك ثم إما أن يكون لديه سبب وجيه أن لا تفعل ذلك ، أو تنفيذ يحتاج الى اصلاح.أنا لا أفهم لماذا كل الآلية اللازمة التي تعني "حقا مضمنة هذه التعليمات البرمجية" (جانبا شكل رمز تتم كتابتها من قبل مضمنة كان حولها).أنا أيضا لا أفهم فكرة أن ذكر أن "إذا كان سخيف جدا أن يكون في وظيفة".بالتأكيد أي قطعة من التعليمات البرمجية التي تأخذ المدخلات تنتج الناتج هو أفضل وضع في وظيفة.أعتقد أنني قد لا يكون الحصول على ذلك لأنني لا تستخدم الدقيقة أمثلية من الكتابة ج, لكن المعالج يشعر تماما مثل المعقدة حل بعض المشاكل البسيطة.

هل كانت مفيدة؟

المحلول

أنا في نهاية المطاف الحاجة إلى تذكر ما الماكرو هو البديل في رأسي وأنا أقرأ.

ويبدو أن تنعكس سلبا على تسمية وحدات الماكرو.أفترض أنك لن تضطر إلى محاكاة المعالج إذا كانت log_function_entry() الماكرو.

تلك التي كنت قد واجهت التي كانت بديهية وسهلة الفهم دائما مثل ميني وظائف, لذلك أنا دائما أتساءل لماذا لم تكن مجرد وظائف.

عادة ما ينبغي, إلا إذا كانت بحاجة للعمل على معايير عامة.

#define max(a,b) ((a)<(b)?(b):(a))

سوف تعمل على أي نوع مع < المشغل.

أكثر من مجرد وظائف وحدات الماكرو تتيح لك تنفيذ عمليات استخدام الرموز في الملف المصدر.هذا يعني أنه يمكنك إنشاء متغير جديد اسمه أو مرجع الملف المصدر و رقم السطر الكلي على.

في C99, وحدات الماكرو أيضا تسمح لك لاستدعاء variadic وظائف مثل printf

#define log_message(guard,format,...) \
   if (guard) printf("%s:%d: " format "\n", __FILE__, __LINE__,__VA_ARGS_);

log_message( foo == 7, "x %d", x)

الذي شكل تعمل مثل printf.إذا كان الحارس هو صحيح ، فإنه إخراج الرسالة جنبا إلى جنب مع الملف و رقم السطر الذي طبع الرسالة.إذا كان استدعاء دالة ، فإنه لا يعرف ملف الخط الذي يطلق عليه من قبل ، vaprintf سيكون العمل أكثر قليلا.

نصائح أخرى

هذا مقتطف يلخص وجهة نظري في هذا الشأن ، من خلال مقارنة عدة طرق C وحدات الماكرو تستخدم ، وكيفية تنفيذها في D.

نسخ من DigitalMars.com

عندما C اخترع, مترجم التكنولوجيا البدائية.تركيب نص ماكرو المعالج على الجبهة الغاية كانت واضحة وسهلة لإضافة العديد من الميزات القوية.على زيادة حجم و تعقيد برامج يتضح أن هذه الميزات تأتي مع العديد من المتأصلة المشاكل. D لا قبل المعالج.ولكن D يوفر أكثر قابلة للتطوير يعني أن حل نفسه المشاكل.

وحدات الماكرو

المعالج وحدات الماكرو إضافة ميزات قوية و المرونة C.ولكن لديهم السلبي:

  • وحدات الماكرو قد لا مفهوم النطاق ؛ فهي صحيحة من وجهة التعريف إلى نهاية المصدر.قطعوا رقعة عبر .ساعة ملفات متداخلة رمز ، إلخ.عندما #include'جي عشرات الآلاف من خطوط تعريفات الماكرو ، يصبح إشكالية لتجنب انفجارها الكلي التوسعات.
  • وحدات الماكرو غير معروفة إلى المصحح.محاولة تصحيح البرنامج مع رمزية البيانات التي تقوض المصحح فقط معرفة الكلي التوسعات ، وليس وحدات الماكرو أنفسهم.
  • وحدات الماكرو تجعل من المستحيل tokenize شفرة المصدر ، في وقت سابق من التغير الكلي يمكن أن تعسفي إعادة الرموز.
  • بحتة النصية أساس وحدات الماكرو يؤدي إلى التعسفي وغير متناسقة الاستخدام ، مما يجعل التعليمات البرمجية باستخدام وحدات الماكرو خطأ عرضة.(محاولة حل هذا وقدم مع قوالب C++.)
  • وحدات الماكرو لا تزال تستخدم لتعويض العجز في اللغة هو القدرة على التعبير ، مثل "مغلفة" حول رأس الملفات.

هنا حصر الاستخدامات الشائعة وحدات الماكرو و المقابلة ميزة في د:

  1. تعريف الحرفي الثوابت:

    • على C المعالج الطريقة

      #define VALUE 5
      
    • على D طريقة

      const int VALUE = 5;
      
  2. إنشاء قائمة من القيم أو الأعلام:

    • على C المعالج الطريقة

      int flags:
      #define FLAG_X  0x1
      #define FLAG_Y  0x2
      #define FLAG_Z  0x4
      ...
      flags |= FLAG_X;
      
    • على D طريقة

      enum FLAGS { X = 0x1, Y = 0x2, Z = 0x4 };
      FLAGS flags;
      ...
      flags |= FLAGS.X;
      
  3. وظيفة الإعداد الاتفاقيات الدعوة:

    • على C المعالج الطريقة

      #ifndef _CRTAPI1
      #define _CRTAPI1 __cdecl
      #endif
      #ifndef _CRTAPI2
      #define _CRTAPI2 __cdecl
      #endif
      
      int _CRTAPI2 func();
      
    • على D طريقة

      داعيا الاتفاقيات يمكن أن تكون محددة في كتل ، لذلك ليس هناك حاجة إلى تغييره لكل وظيفة:

      extern (Windows)
      {
          int onefunc();
          int anotherfunc();
      }
      
  4. بسيطة البرمجة العامة:

    • على C المعالج الطريقة

      اختيار أي وظيفة لاستخدام استنادا إلى نص الاستبدال:

      #ifdef UNICODE
      int getValueW(wchar_t *p);
      #define getValue getValueW
      #else
      int getValueA(char *p);
      #define getValue getValueA
      #endif
      
    • على D طريقة

      D تمكن إعلانات الرموز التي هي الأسماء المستعارة من الرموز الأخرى:

      version (UNICODE)
      {
          int getValueW(wchar[] p);
          alias getValueW getValue;
      }
      else
      {
          int getValueA(char[] p);
          alias getValueA getValue;
      }
      

وهناك المزيد من الأمثلة على DigitalMars الموقع.

فهي لغة البرمجة (أبسط واحد) على رأس ج ، لذلك فهي مفيدة للقيام metaprogramming في وقت الترجمة...وبعبارة أخرى, يمكنك كتابة التعليمات البرمجية للماكرو الذي يقوم بإنشاء التعليمات البرمجية C في أقل خطوط الوقت الذي سيستغرق الكتابة مباشرة في C.

فهي أيضا مفيدة جدا في كتابة "وظيفة مثل" العبارات التي هي "متعددة الأشكال" أو "زائد";على سبيل المثالماكس الكلي النحو التالي:

#define max(a,b) ((a)>(b)?(a):(b))

مفيد لأي نوع عددي;و في " ج " أنت لا تستطيع أن تكتب:

int max(int a, int b) {return a>b?a:b;}
float max(float a, float b) {return a>b?a:b;}
double max(double a, double b) {return a>b?a:b;}
...

حتى إذا كنت تريد لأنك لا يمكن أن تفرط وظائف.

و ناهيك عن المشروط تجميع الملفات بما في ذلك (التي هي أيضا جزء من لغة الماكرو)...

وحدات الماكرو تسمح لشخص ما أن تعديل السلوك البرنامج خلال تجميع الوقت.النظر في هذا:

  • ج الثوابت تسمح تثبيت برنامج السلوك في وقت التطوير
  • ج المتغيرات يسمح برنامج تعديل السلوك في وقت التنفيذ
  • ج وحدات الماكرو تسمح بتعديل السلوك البرنامج في تجميع الوقت

في تجميع الوقت يعني غير مستخدمة لن يذهب حتى إلى الثنائية و أن بناء عملية يمكن تعديل قيم طالما انها تتكامل مع الماكرو المعالج.على سبيل المثال:جعل القوس=ذراع (يفترض توجيه تعريف الماكرو كما cc-DARCH=الذراع)

أمثلة بسيطة:(من سي العمومية حدود.ساعة, تعريف أكبر قيمة من الطويل)

#if __WORDSIZE == 64
#define LONG_MAX 9223372036854775807L
#else
#define LONG_MAX 2147483647L
#endif

يتحقق (باستخدام #define __WORDSIZE) في وقت الترجمة إذا نحن تجميع 32 أو 64 بت.مع multilib toolchain باستخدام المعلمات -m32 و -m64 قد تتغير تلقائيا بت الحجم.

(POSIX نسخة الطلب)

#define _POSIX_C_SOURCE 200809L

الطلبات خلال تجميع الوقت POSIX 2008 الدعم.المكتبة القياسية قد دعم العديد من (غير متوافقة) المعايير ولكن مع هذا التعريف ، وسوف توفر وظيفة الصحيح النماذج (على سبيل المثال:getline () لا يحصل () ، إلخ.).إذا كانت المكتبة لا تدعم معيار قد تعطي #خطأ أثناء وقت التحويل بدلا من تحطمها أثناء التنفيذ ، على سبيل المثال.

(ضمنية المسار)

#ifndef LIBRARY_PATH
#define LIBRARY_PATH "/usr/lib"
#endif

يحدد خلال تجميع الوقت هاردكودي الدليل.يمكن أن تتغير مع DLIBRARY_PATH=/home/user/lib ، على سبيل المثال.إذا كانت const char * كيف يمكنك تكوين خلال تجميع ?

(pthread.ساعة, تعاريف معقدة في وقت الترجمة)

# define PTHREAD_MUTEX_INITIALIZER \
  { { 0, 0, 0, 0, 0, 0, { 0, 0 } } }

أجزاء كبيرة من النص قد خلاف ذلك لن تكون مبسطة قد أعلن (دائما في وقت الترجمة).ليس من الممكن أن تفعل هذا مع الوظائف أو الثوابت (في وقت الترجمة).

لتجنب حقا تعقيد الأمور وتجنب مما يشير إلى ضعف الترميز الأساليب ، أنا لن أعطي مثال من التعليمات البرمجية التي تجمع في مختلف يتعارض وأنظمة التشغيل.استخدام الخاص بك عبر بناء نظام ذلك ، ولكن يجب أن يكون واضحا أن المعالج يسمح ذلك دون مساعدة من بناء نظام دون كسر تجميع بسبب غياب الواجهات.

وأخيرا فكر في أهمية الترجمة الشرطية على النظم المضمنة ، حيث سرعة المعالج والذاكرة محدودة أنظمة غير متجانسة للغاية.

الآن, إذا كنت تسأل هل من الممكن استبدال كافة الكلي المستمر تعريفات المكالمات وظيفة مناسبة التعاريف ؟ الجواب هو نعم لكن لن ببساطة جعل الحاجة إلى تغيير السلوك البرنامج خلال تجميع تذهب بعيدا.المعالج لا يزال مطلوبا.

تذكر أن وحدات الماكرو (قبل المعالج) تأتي من الأيام الأولى من C.أنها اعتادت أن تكون الطريقة الوحيدة للقيام مضمنة 'وظائف' (لأنه بالطبع مضمنة جدا الكلمة الأخيرة) و أنها لا تزال القوة ما يكون المضمنة.

أيضا, وحدات الماكرو هي الطريقة الوحيدة التي يمكن أن تفعل مثل هذه الحيل إدراج ملف الخط في ثوابت السلسلة في وقت الترجمة.

في هذه الأيام العديد من الأشياء التي تستخدم وحدات الماكرو إلى أن الطريقة الوحيدة هي الأفضل التعامل معها من خلال آليات جديدة.ولكن لا يزال لديهم مكانها من وقت لآخر.

وبصرف النظر عن مصدر في الكفاءة و الشرطية ، وحدات الماكرو يمكن استخدامها لرفع مستوى التجريد من مستوى منخفض ج التعليمات البرمجية.ج لا عزل من التفاصيل الجوهرية من الذاكرة و إدارة الموارد و تخطيط دقيق من البيانات ، ويدعم محدودة جدا من أشكال إخفاء المعلومات وغيرها من آليات إدارة النظم الكبيرة.مع وحدات الماكرو لم تعد تقتصر فقط باستخدام قاعدة يبني في لغة C:يمكنك تحديد الخاصة بك هياكل البيانات والترميز بنيات (بما في ذلك فصول والقوالب!) في حين لا تزال أبعاده كتابة C!

المعالج وحدات الماكرو في الواقع تقدم تورينج-كاملة اللغة أعدم في وقت الترجمة.واحدة من للإعجاب (قليلا مخيف) أمثلة على هذا الأمر على C++ الجانب:على دفعة المعالج مكتبة يستخدم C99/C++98 المعالج لبناء (نسبيا) آمنة البرمجة بنيات ثم توسعت إلى ما وراء الإعلانات و يمكنك إدخال رمز ، سواء C أو C++.

في الممارسة, أنصح بخصوص المعالج البرمجة كملاذ أخير عندما لا يكون لديك حرية استخدام مستوى عال يبني في أكثر أمانا اللغات.ولكن في بعض الأحيان أنه من الجيد أن تعرف ما يمكنك القيام به إذا كان ظهرك إلى الحائط و الجرذان تقترب...!

من الكمبيوتر Stupidities:

لقد رأيت هذا الرمز مقتطفات في الكثير من الألعاب مجانية برامج يونكس:

/*
* بت القيم.
*/
#تعريف BIT_0 1
#تعريف BIT_1 2
#تعريف BIT_2 4
#تعريف BIT_3 8
#تعريف BIT_4 16
#تعريف BIT_5 32
#تعريف BIT_6 64
#تعريف BIT_7 128
#تعريف BIT_8 256
#تعريف BIT_9 512
#تعريف BIT_10 1024
#تعريف BIT_11 2048
#تعريف BIT_12 4096
#تعريف BIT_13 8192
#تعريف BIT_14 16384
#تعريف BIT_15 32768
#تعريف BIT_16 65536
#تعريف BIT_17 131072
#تعريف BIT_18 262144
#تعريف BIT_19 524288
#تعريف BIT_20 1048576
#تعريف BIT_21 2097152
#تعريف BIT_22 4194304
#تعريف BIT_23 8388608
#تعريف BIT_24 16777216
#تعريف BIT_25 33554432
#تعريف BIT_26 67108864
#تعريف BIT_27 134217728
#تعريف BIT_28 268435456
#تعريف BIT_29 536870912
#تعريف BIT_30 1073741824
#تعريف BIT_31 2147483648

أسهل طريقة لتحقيق ذلك هي:

#تعريف BIT_0 0x00000001
#تعريف BIT_1 0x00000002
#تعريف BIT_2 0x00000004
#تعريف BIT_3 0x00000008
#تعريف BIT_4 0x00000010
...
#تعريف BIT_28 0x10000000
#تعريف BIT_29 0x20000000
#تعريف BIT_30 0x40000000
#تعريف BIT_31 0x80000000

طريقة أسهل لا يزال هو السماح مترجم القيام بعمليات حسابية:

#تعريف BIT_0 (1)
#تعريف BIT_1 (1 << 1)
#تعريف BIT_2 (1 << 2)
#تعريف BIT_3 (1 << 3)
#تعريف BIT_4 (1 << 4)
...
#تعريف BIT_28 (1 << 28)
#تعريف BIT_29 (1 << 29)
#تعريف BIT_30 (1 << 30)
#تعريف BIT_31 (1 << 31)

ولكن لماذا كل هذه المشاكل من تحديد 32 الثوابت?لغة C أيضا معلمات وحدات الماكرو.كل ما تحتاجه حقا هو:

#تعريف بت(×) (1 << (x))

على أي حال, أنا أتساءل عما إذا كان الشخص الذي كتب رمز الأصلي استخدام آلة حاسبة أو فقط تحسب كل شيء على الورق.

هذا مجرد واحد من الممكن استخدام وحدات الماكرو.

واحدة من هذه القضية حيث وحدات الماكرو تألق حقا هو عندما تفعل رمز الجيل معهم.

كنت أعمل على C++ نظام باستخدام البرنامج المساعد النظام مع طريقة تمرير المعلمات إلى البرنامج المساعد (باستخدام خريطة مخصصة مثل هيكل).بسيطة بعض وحدات الماكرو كانت تستخدم لتكون قادرة على التعامل مع هذه المراوغة و يسمح لنا لاستخدام الحقيقي C++ والوظائف مع المعايير العادية في الإضافات دون الكثير من المشاكل.كل الغراء التعليمات البرمجية التي يتم إنشاؤها من قبل وحدات الماكرو.

وأود أن أضيف إلى ما سبق أن قيل.

لأن وحدات الماكرو العمل على النص بدائل أنها تسمح لك فعل أشياء مفيدة جدا التي لن يكون من الممكن القيام باستخدام وظائف.

هنا بعض الحالات التي تكون فيها وحدات الماكرو يمكن أن تكون مفيدة حقا:

/* Get the number of elements in array 'A'. */
#define ARRAY_LENGTH(A) (sizeof(A) / sizeof(A[0]))

هذه هي شعبية جدا وكثيرا ما تستخدم الماكرو.هذا مفيد جدا عندما كنت على سبيل المثال تحتاج إلى تكرار خلال صفيف.

int main(void)
{
    int a[] = {1, 2, 3, 4, 5};
    int i;
    for (i = 0; i < ARRAY_LENGTH(a); ++i) {
        printf("a[%d] = %d\n", i, a[i]);
    }
    return 0;
}

هنا لا يهم إذا كان آخر مبرمج يضيف خمسة عناصر a في التصريح.على for-حلقة دائما تكرار خلال كافة العناصر.

ج مكتبة وظائف مقارنة الذاكرة و السلاسل هي قبيحة جدا للاستخدام.

يمكنك كتابة:

char *str = "Hello, world!";

if (strcmp(str, "Hello, world!") == 0) {
    /* ... */
}

أو

char *str = "Hello, world!";

if (!strcmp(str, "Hello, world!")) {
    /* ... */
}

للتحقق مما إذا str نقاط "Hello, world".أنا شخصيا أعتقد أن كل هذه الحلول تبدو قبيحة جدا ومربكة (خاصة !strcmp(...)).

هنا نوعان أنيق وحدات الماكرو بعض الناس (بما فيهم أنا) تستخدم عند الحاجة إلى مقارنة السلاسل أو الذاكرة باستخدام strcmp/memcmp:

/* Compare strings */
#define STRCMP(A, o, B) (strcmp((A), (B)) o 0)

/* Compare memory */
#define MEMCMP(A, o, B) (memcmp((A), (B)) o 0)

الآن يمكنك الآن كتابة رمز مثل هذا:

char *str = "Hello, world!";

if (STRCMP(str, ==, "Hello, world!")) {
    /* ... */
}

هنا هو نية الكثير أكثر وضوحا!

هذه هي الحالات وحدات الماكرو تستخدم لأشياء وظائف لا يمكن تحقيقه.وحدات الماكرو لا ينبغي أن تستخدم لاستبدال وظائف ولكن لديهم الأخرى استخدامات جيدة.

نظرا التعليقات في سؤالك قد لا نقدر أن الدعوة وظيفة يمكن أن تنطوي على قدر كبير من النفقات العامة.المعلمات الرئيسية السجلات قد يكون نسخها إلى كومة على الطريق في كومة المساس بها على طريقة للخروج.هذا صحيح بصفة خاصة من كبار السن رقائق إنتل.وحدات الماكرو السماح مبرمج الحفاظ على التجريد من الوظيفة (تقريبا) ، ولكن تجنب النفقات العامة مكلفة استدعاء دالة.مضمنة الكلمة هو الاستشارية ، ولكن المترجم قد لا دائما الحصول على ذلك الحق.المجد خطر 'ج' هو أنه يمكنك عادة ثني التحويل البرمجي الخاص بك سوف.

في الخبز والزبدة اليومية برمجة تطبيقات هذا النوع من الصغرى الأمثل (تجنب المكالمات وظيفة) هو أسوأ عموما ثم لا طائل منه ، ولكن إذا كنت تكتب في الوقت الحاسم من خلال وظيفة تسمى نواة نظام التشغيل ، ثم أنها يمكن أن تحدث فرقا كبيرا.

على عكس الوظائف العادية, يمكنك أن تفعل التحكم في التدفق (إذا ، في حين،،...) وحدات الماكرو.هنا مثال:

#include <stdio.h>

#define Loop(i,x) for(i=0; i<x; i++)

int main(int argc, char *argv[])
{
    int i;
    int x = 5;
    Loop(i, x)
    {
        printf("%d", i); // Output: 01234
    } 
    return 0;
} 

انها جيدة بالنسبة inlining رمز وتجنب استدعاء دالة النفقات العامة.فضلا عن استخدامه إذا كنت ترغب في تغيير السلوك في وقت لاحق دون تحرير الكثير من الأماكن.انها ليست مفيدة في أشياء معقدة ، ولكن خطوط بسيطة من التعليمات البرمجية التي تريد مضمنة, انها ليست سيئة.

من خلال الاستفادة ج المعالج نص التلاعب واحد يمكن بناء ج أي ما يعادل متعددة الأشكال بنية البيانات.باستخدام هذه التقنية يمكننا بناء موثوق بها الأدوات البدائية هياكل البيانات التي يمكن استخدامها في أي برنامج C, لأنها تستفيد من جملة C و لا تفاصيل أي تنفيذ.

شرح مفصل عن كيفية استخدام وحدات الماكرو في إدارة هيكل البيانات الواردة هنا - http://multi-core-dump.blogspot.com/2010/11/interesting-use-of-c-macros-polymorphic.html

وحدات الماكرو تمكنك من التخلص من نسخ-لصق الأجزاء التي لا يمكن القضاء عليها بأي طريقة أخرى.

على سبيل المثال (الرمز الحقيقي, جملة VS 2010 مترجم):

for each (auto entry in entries)
{
        sciter::value item;
        item.set_item("DisplayName",    entry.DisplayName);
        item.set_item("IsFolder",       entry.IsFolder);
        item.set_item("IconPath",       entry.IconPath);
        item.set_item("FilePath",       entry.FilePath);
        item.set_item("LocalName",      entry.LocalName);
        items.append(item);
    }

هذا هو المكان حيث يمكنك تمرير قيمة الحقل تحت نفس الاسم في محرك السيناريو.هل هذا نسخ-لصق ؟ نعم. DisplayName يتم استخدام سلسلة النصي كما حقل اسم المترجم.هو بهذا السوء ؟ نعم.إذا كنت ريفاكتور أنت رمز إعادة تسمية LocalName إلى RelativeFolderName (كما فعلت) و تنسى أن تفعل الشيء نفسه مع سلسلة (كما فعلت) ، فإن البرنامج سيعمل بطريقة لا تتوقع (في الواقع, في بلدي على سبيل المثال يعتمد على هل نسيت أن تسمية الميدان في ملف نصي مستقل ، ولكن إذا كان البرنامج النصي يستخدم التسلسل سيكون 100% علة).

إذا كنت تستخدم ماكرو لهذا لن يكون هناك مجالا علة:

for each (auto entry in entries)
{
#define STR_VALUE(arg) #arg
#define SET_ITEM(field) item.set_item(STR_VALUE(field), entry.field)
        sciter::value item;
        SET_ITEM(DisplayName);
        SET_ITEM(IsFolder);
        SET_ITEM(IconPath);
        SET_ITEM(FilePath);
        SET_ITEM(LocalName);
#undef SET_ITEM
#undef STR_VALUE
        items.append(item);
    }

للأسف, هذا يفتح الباب أمام أنواع أخرى من الحشرات.يمكنك ان تجعل من الخطأ المطبعي في كتابة الماكرو و لن ترى مدلل رمز لأن المترجم لا تظهر كيف تبدو بعد كل تجهيزها.شخص آخر يمكن أن تستخدم نفس الاسم (هذا هو السبب في أنني "الافراج" وحدات الماكرو في اسرع وقت ممكن مع #undef).لذا استخدامها بحكمة.إذا كنت ترى طريقة أخرى للتخلص من نسخ-لصق التعليمات البرمجية (مثل وظائف), استخدام هذه الطريقة.إذا كنت ترى أن التخلص من نسخ-لصق التعليمات البرمجية مع وحدات الماكرو لا يستحق النتيجة ، والحفاظ على نسخ-لصق التعليمات البرمجية.

واحد من الأسباب الواضحة هو أنه باستخدام الماكرو البرمجية سيتم توسيعها في وقت الترجمة ، وتحصل الزائفة وظيفة الاتصال بدون دعوة علوية.

وإلا, يمكنك أيضا استخدامه رمزية الثوابت ، بحيث لم يكن لديك إلى تحرير نفس القيمة في عدة أماكن إلى تغيير شيء واحد صغير.

وحدات الماكرو ..عندما الخاص بك &#(*$& مترجم يرفض مضمنة شيء.

التي ينبغي أن تكون تحفيزية الملصق ؟

بكل جدية, جوجل المعالج الاعتداء (قد نرى مماثل لذلك السؤال #1 نتيجة).إذا أنا أكتب الكلي الذي يتجاوز وظائف تأكيد(), أنا عادة في محاولة لمعرفة إذا كان لي أن المترجم في الواقع مضمنة وظيفة مماثلة.

الآخرين سوف يجادل ضد باستخدام #إذا الشرطية ..أنها تفضل:

if (RUNNING_ON_VALGRIND)

بدلا من

#if RUNNING_ON_VALGRIND

..لأغراض التصحيح ، حيث يمكنك أن ترى إذا() ولكن ليس #إذا في مصحح أخطاء.ثم نغوص في #ifdef vs #إذا.

إذا كان أقل من 10 أسطر من التعليمات البرمجية ، في محاولة مضمنة ذلك.إذا لا يمكن أن يكون المضمنة ، في محاولة لتحسين ذلك.إذا كان سخيف جدا أن تكون وظيفة ، وجعل الماكرو.

بينما أنا لست مروحة كبيرة من وحدات الماكرو و لا تميل إلى كتابة الكثير C بعد الآن ، استنادا إلى بلدي الحالي المهام ، شيء من هذا القبيل (والتي يمكن أن يكون من الواضح أن بعض الآثار الجانبية) هو مناسب:

#define MIN(X, Y)  ((X) < (Y) ? (X) : (Y))

الآن أنا لم أكتب أي شيء مثل ذلك منذ سنوات ، ولكن 'وظائف' مثل التي كانت في جميع أنحاء رمز المحافظة في وقت سابق في مسيرتي.أعتقد أن التوسع يمكن أن تعتبر مريحة.

لم أر أحدا ذكر هذا حتى فيما يتعلق وظيفة مثل وحدات الماكرو ، على سبيل المثال:

#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))

عموما من المستحسن تجنب استخدام وحدات الماكرو عند عدم الضرورة ، لأسباب عديدة ، القراءة يجري القلق الرئيسي.لذلك:

متى يجب استخدام هذه أكثر من وظيفة ؟

أبدا تقريبا ، حيث أن هناك أكثر قابلية للقراءة البديلة التي inline, انظر https://www.greenend.org.uk/rjk/tech/inline.html أو http://www.cplusplus.com/articles/2LywvCM9/ (الوصلة الثانية هي C++ الصفحة ، ولكن النقطة تنطبق ج المجمعين بقدر ما أعرف).

الآن اختلاف طفيف هو أن وحدات الماكرو يتم التعامل معها من قبل معالج مضمن يتم التعامل معها من قبل مترجم, ولكن لا يوجد فرق عملي في الوقت الحاضر.

متى يكون من المناسب استخدام هذه ؟

عن وظائف صغيرة (اثنين أو ثلاثة من المتشددين ماكس).الهدف هو الحصول على بعض المزايا أثناء تشغيل البرنامج ، كما تعمل مثل وحدات الماكرو (و وظائف مضمنة) هي رمز بدائل القيام به خلال فترة ما قبل تنفيذ (أو تجميع في حالة مضمنة) و ليست حقيقية وظائف تعيش في الذاكرة ، لذلك لا يوجد استدعاء دالة النفقات العامة (المزيد من التفاصيل في الصفحات المرتبطة).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top