C MULTI-LINE MACRO: DO / TERWIJL (0) VS SCOPE BLOKEN [DUPLICEER]

Mogelijke duplicaten:
Wat is het gebruik van doen tijdens het gebruik van (0) wanneer We definiëren een macro?
Waarom zijn er soms zinloos doen / terwijl / of / anders uitspraken in C / C++ macro’s?
do {…} terwijl (0) Waar is het goed voor?

Ik heb enkele multi-line C macro’s gezien die in een do / while (0) lus zoals:

zijn ingepakt

#define foo \ \
 doen { \
  do_stuff_here \
  do_more_stuff \
 } terwijl (0)

Wat zijn de voordelen (indien aanwezig) van het schrijven van de code op die manier in tegenstelling tot het gebruik van een basisblok:

#define foo \ \
 {\
  do_stuff_here \
  do_more_stuff \
 }

Antwoord 1, Autoriteit 100%

Andrey Tarasevich biedt de volgende uitleg:

  1. op Google-groepen
  2. op bytes.com

[kleine wijzigingen in gemaakte opmaak. Parenthetische annotaties toegevoegd in vierkante haakjes []].

Het hele idee van het gebruik van ‘do / while’-versie is om een ​​macro te maken die dat zal doen
uitbreiden tot een reguliere verklaring, niet in een samengestelde verklaring. Dit is
gedaan om het gebruik van function-stijl macro’s uniform te maken met de
gebruik van gewone functies in alle contexten.

Overweeg de volgende codeschets:

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

Waar fooen barzijn gewone functies. Stel je nu voor dat je dat zou doen
Graag functie vervangen foomet een macro van de bovenstaande aard [genoemd CALL_FUNCS]:

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

Nu, als uw macro is gedefinieerd in overeenstemming met de tweede aanpak
(Alleen {en }) De code zal niet langer compileren, omdat de true ‘
Tak van ifnu vertegenwoordigd is door een samengestelde verklaring. En wanneer jij
Zet een ;na deze compound-instructie, bent u klaar met de hele if
Verklaring, dus het wezen van de elseBranch (vandaar de compilatiefout).

One Way to Corrigeer dit probleem is om niet te onthouden om niet ;na te leggen
Macro “aanroepingen”:

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

Dit zal samenstellen en werken zoals verwacht, maar dit is niet uniform. De
Meer elegante oplossing is om ervoor te zorgen dat macro zich uitbreidt tot een normale
verklaring, niet in een verbinding één. Een manier om te bereiken, is om te definiëren
de macro als volgt:

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

Nu deze code:

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

zal zonder problemen compileren.

Let echter op het kleine maar belangrijke verschil tussen mijn definitie
van CALL_FUNCSen de eerste versie in uw bericht. Ik heb geen
;na } while (0). Een ;aan het einde van die definitie plaatsen
zou onmiddellijk het volledige punt verslaan van het gebruik van ‘do / while’ en maken
die macro vrijwel gelijk aan de versie van de compound-statement.

Ik weet niet waarom de auteur van de code die u in uw origineel citeert
Bericht Plaats dit ;na while (0). In deze vorm zijn beide varianten
equivalent. Het hele idee achter het gebruik van ‘Do / While’-versie is niet
neem deze laatste ;op in de macro (om de redenen die ik heb uitgelegd
hierboven).

Other episodes