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




multiline (2)

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 \
  }

بالنسبة إلى الزائرين المستقبليين الذين قد يهتمون بمعرفة شرائح الذاكرة هذه ، فإنني أكتب نقاط مهمة حول 5 شرائح ذاكرة في C:

بعض الرؤساء:

  1. عند تنفيذ برنامج C ، يتم تخصيص بعض الذاكرة في ذاكرة الوصول العشوائي (RAM) لتنفيذ البرنامج. يتم استخدام هذه الذاكرة لتخزين التعليمات البرمجية التي يتم تنفيذها بشكل متكرر (البيانات الثنائية) ، ومتغيرات البرنامج ، وما إلى ذلك. وتتحدث شرائح الذاكرة التالية عن نفسها:
  2. عادة ما يكون هناك ثلاثة أنواع من المتغيرات:
    • المتغيرات المحلية (تسمى أيضًا المتغيرات التلقائية في C)
    • المتغيرات العالمية
    • المتغيرات الساكنة
    • يمكن أن يكون لديك متغيرات ثابتة ثابتة أو ساكنة محلية ، ولكن الثلاثة السابقة هي الأنواع الرئيسية.

5 شرائح الذاكرة في C:

1. مقطع التعليمات البرمجية

  • جزء الرمز ، الذي يُشار إليه أيضًا باسم جزء النص ، هو مساحة الذاكرة التي تحتوي على الشفرة التي يتم تنفيذها بشكل متكرر.
  • غالباً ما يكون مقطع التعليمات البرمجية للقراءة فقط لتجنب المخاطرة من تجاوز بواسطة برمجة الأخطاء مثل buffer-overflow ، إلخ.
  • لا يحتوي جزء الشفرة على متغيرات البرنامج مثل المتغير المحلي ( يطلق عليه أيضًا المتغيرات التلقائية في C ) ، والمتغيرات العامة ، وما إلى ذلك.
  • استنادًا إلى تطبيق C ، يمكن أن تحتوي قطعة الرمز أيضًا على قيم حرفيّة للقراءة فقط. على سبيل المثال ، عند القيام printf("Hello, world") ، يتم إنشاء سلسلة "Hello، world" في مقطع التعليمات البرمجية / النص. يمكنك التحقق من هذا الأمر باستخدام size في نظام التشغيل Linux.
  • قراءة متعمقة

جزء البيانات

جزء البيانات مقسّم في الأجزاء أدناه اثنين وعادةً ما يقع أسفل منطقة كومة الذاكرة المؤقتة أو في بعض التطبيقات فوق المكدس ولكن الجزء البيانات لا تقع أبداً بين كومة الذاكرة المؤقتة ومنطقة مكدس الذاكرة المؤقتة.

2. جزء البيانات غير مهيأ

  • يُعرف هذا المقطع أيضًا باسم bss .
  • هذا هو جزء من الذاكرة التي تحتوي على:
    1. المتغيرات العالمية غير المحددة (بما في ذلك متغيرات المؤشر)
    2. متغيرات عالمية ثابتة غير محددة .
    3. متغيرات ثابتة محلية غير محددة .
  • سيتم تخزين أي متغير محلي عالمي أو ثابت لم يتم تهيئته في مقطع البيانات غير مهيأ
  • على سبيل المثال: المتغير العالمي int globalVar; أو متغير محلي static int localStatic; سيتم تخزينها في جزء البيانات غير مهيأ.
  • إذا قمت بتعريف متغير عمومي وتهيئته كـ 0 أو NULL فستظل تشير إلى مقطع بيانات غير مهيأ أو bss.
  • قراءة متعمقة

3. الجزء البيانات الأولية

  • هذا القطاع يخزن:
    1. المتغيرات العالمية الأولية (بما في ذلك متغيرات المؤشر)
    2. المتغيرات العالمية الثابتة الأولية .
    3. المتغيرات الساكنة المحلية الأولية .
  • على سبيل المثال: المتغير الشامل int globalVar = 1; أو متغير محلي static int localStatic = 1; سيتم تخزينها في جزء البيانات التهيئة.
  • يمكن تصنيف هذا المقطع إلى منطقة للقراءة فقط مبدئية ومنطقة للقراءة والكتابة . ستدخل المتغيرات العمومية الثابتة الأولية في منطقة القراءة فقط ، بينما ستذهب المتغيرات التي يمكن تعديل قيمها في وقت التشغيل في منطقة القراءة والكتابة التي تم تأليفها .
  • يتم تحديد حجم هذه الشريحة من خلال حجم القيم في التعليمات البرمجية المصدر للبرنامج ، ولا يتغير في وقت التشغيل .
  • قراءة متعمقة

4. شريحة المكدس

  • يتم استخدام جزء المكدس لتخزين المتغيرات التي يتم إنشاؤها داخل الوظائف ( يمكن أن تكون الوظيفة هي الوظيفة الرئيسية أو وظيفة محددة من قبل المستخدم ) ، مثل المتغير
    1. المتغيرات المحلية للدالة (بما في ذلك متغيرات المؤشر)
    2. الحجج التي تم تمريرها لتعمل
    3. اعد العنوان
  • ستتم إزالة المتغيرات المخزنة في المكدس بمجرد انتهاء تنفيذ الدالة.
  • قراءة متعمقة

5. جزء الكومة

  • هذا الجزء هو دعم تخصيص الذاكرة الديناميكية. إذا أراد المبرمج أن يخصص بعض الذاكرة بشكل حيوي ، فإنه في C يتم ذلك باستخدام malloc ، calloc ، أو طرق realloc .
  • على سبيل المثال ، عندما يكون int* prt = malloc(sizeof(int) * 2) سيتم تخصيص ثمانية بايت في كومة الذاكرة المؤقتة وسيتم إرجاع عنوان الذاكرة لذلك الموقع وتخزينه في متغير ptr . سيكون متغير ptr إما في مقطع التكديس أو البيانات اعتمادًا على الطريقة المعلنة / المستخدمة.
  • قراءة متعمقة






c macros multiline