C ماكرو متعدد الأسطر:افعل/أثناء (0) مقابل كتلة النطاق [مكررة]
سؤال
التكرارات المحتملة:
ما فائدة do while(0) عندما نحدد ماكرو؟
لماذا توجد في بعض الأحيان عبارات do/while وif/else لا معنى لها في وحدات الماكرو 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 \ }
المحلول
http://bytes.com/groups/c/219859-do-while-0-macro-substitutions
أندريه تاراسيفيتش:
تتمثل الفكرة الكاملة لاستخدام إصدار "do/بينما" في إنشاء ماكرو يتوسع إلى بيان منتظم ، وليس في بيان مركب.يتم ذلك من أجل استخدام وحدات الماكرو على غرار الوظيفة مع استخدام الوظائف العادية في جميع السياقات.
النظر في رسم التعليمات البرمجية التالي
if (<condition>)
foo(a);
else
bar(a);
حيث تعد "foo" و"bar" وظائف عادية.تخيل الآن أنك ترغب في استبدال الوظيفة "foo" بماكرو من الطبيعة أعلاه
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
الآن ، إذا تم تعريف الماكرو الخاص بك وفقًا للنهج الثاني (فقط "{" و "} ') ، فلن يتم تجميع الكود ، لأن الفرع" الحقيقي "إذا" تم تمثيله الآن ببيان مركب.وعندما تضع "؛" بعد هذا البيان المركب ، انتهيت من بيان "IF" بالكامل ، وبالتالي يتيم الفرع "Else" (وبالتالي خطأ التجميع).
طريقة واحدة لتصحيح هذه المشكلة هي تذكر عدم وضع "؛" بعد "دعوات" الماكرو
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)
.وضع أ ;
في نهاية هذا التعريف ، سيهزم على الفور نقطة استخدام "do/year" وجعل هذا الماكرو يعادل إلى حد كبير إصدار المجموعة المركبة.
لا أعرف لماذا وضع مؤلف الرمز الذي نقلته في رسالتك الأصلية هذا ;
بعد while (0)
.في هذا النموذج كلا المتغيرات مكافئة.إن الفكرة الكاملة وراء استخدام إصدار "do/بينما" لا تضم هذا النهائي ;
في الماكرو (للأسباب التي شرحت أعلاه).