C multi-line macro: do/while(0) vs scope block



macros multiline (1)

http://bytes.com/groups/c/219859-do-while-0-macro-substitutions

أندريه تاراسيفيتش:

إن الفكرة الكاملة لاستخدام إصدار 'do / while' هي جعل الماكرو الذي سيتوسع إلى بيان عادي ، وليس في جملة مركبة. ويتم ذلك من أجل جعل استخدام وحدات الماكرو على غرار الوظيفة موحدة مع استخدام الوظائف العادية في جميع السياقات.

النظر في التعليمات البرمجية التالية

if (<condition>)
  foo(a);
else
  bar(a);

حيث "foo" و "bar" هي وظائف عادية. الآن تخيل أنك تريد استبدال الوظيفة "foo" باستخدام ماكرو من الطبيعة المذكورة أعلاه

if (<condition>)
  CALL_FUNCS(a);
else
  bar(a);

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

إحدى طرق تصحيح هذه المشكلة هي تذكر عدم وضع "؛" بعد ماكرو "دعوات"

if (<condition>)
  CALL_FUNCS(a)
else
  bar(a);

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

#define CALL_FUNCS(x) \
do { \
  func1(x); \
  func2(x); \
  func3(x); \
} while (0)

الآن هذا الرمز

if (<condition>)
  CALL_FUNCS(a);
else
  bar(a);

سوف تترجم دون أي مشاكل.

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

لا أعرف سبب وضع مؤلف الشفرة التي اقتبستها في رسالتك الأصلية هذا ; بعد while (0) . في هذا الشكل كلا المتغيرين متساويين. الفكرة الكاملة وراء استخدام إصدار 'do / while' لا تشمل هذا النهائي ; في الماكرو (للأسباب التي شرحتها أعلاه).

التكرارات الممكنة:
ما فائدة القيام به أثناء (0) عندما نحدد الماكرو؟
لماذا هناك أحياناً لا معنى / هل و / / عبارات آخر في C / C ++ وحدات الماكرو؟
هل {…} بينما (0) ما هو جيد؟

لقد رأيت بعض وحدات الماكرو C متعددة الأسطر التي يتم تغليفها داخل حلقة do / while (0) مثل:

#define FOO \
  do { \
    do_stuff_here \
    do_more_stuff \
  } while (0)

ما هي فوائد (إن وجدت) من كتابة التعليمات البرمجية بهذه الطريقة بدلاً من استخدام كتلة أساسية:

#define FOO \
  { \
    do_stuff_here \
    do_more_stuff \
  }




multiline