http://bytes.com/groups/c/219859-do-while-0-macro-substitutions
Andrey Tarasevich:
Cały pomysł wykorzystania „zrobić/podczas gdy "wersja polega na stworzeniu makra, które będzie się rozwijało w zwykłą instrukcję, a nie w instrukcję złożoną. Jest to zrobione w celu ujednolicenia makr w stylu funkcji przy użyciu zwykłych funkcji we wszystkich kontekstach.
Rozważmy Kodeksu Poniższe szkic
if (<condition>)
foo(a);
else
bar(a);
gdzie 'foo' i 'bar' są zwykłe funkcje. Teraz wyobraź sobie, że chcesz chciał zastąpić funkcję „foo” z makro z powyższym charakterze
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
teraz, jeśli makro jest zdefiniowane zgodnie z drugim podejściu (tylko „{” i „} ") kod nie będzie się już kompilował, ponieważ" prawdziwa "gałąź" if " jest teraz reprezentowana przez instrukcję złożoną. A kiedy podasz wstaw ";" po tym złożonym stwierdzeniu zakończyłeś całą instrukcję "if" , osierocając gałąź "else" (stąd błąd kompilacji).
Jednym ze sposobów rozwiązania tego problemu jest pamiętanie, aby nie wstawiać ";" po makro „wywołania”
if (<condition>)
CALL_FUNCS(a)
else
bar(a);
To będzie skompilować i działa zgodnie z oczekiwaniami, ale to nie jest jednolita. Bardziej eleganckie rozwiązanie polega na upewnieniu się, że makro rozwija się w zwykłe oświadczenie , a nie w złożone. Jednym ze sposobów osiągnięcia tego celu jest zdefiniowanie makro następująco
#define CALL_FUNCS(x) \
do { \
func1(x); \
func2(x); \
func3(x); \
} while (0)
Teraz ten kod
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
zostanie skompilowany bez żadnych problemów.
Należy jednak zauważyć niewielką, ale istotną różnicę między moją definicją z CALL_FUNCS
a pierwszą wersją w wiadomości. Nie wstawiłem ;
po } while (0)
.Umieszczenie ;
na końcu definicji natychmiast zniszczyłoby cały punkt użycia 'do/while' i uczyniłoby z niego jednoznacznie równoważne z wersją złożoną.
Nie wiem, dlaczego autor kodu, który cytowałeś w oryginalnym komunikacie , umieścił ten ;
po while (0)
. W tej postaci oba warianty są równoważne w postaci . Cała idea używania wersji "do/while" nie jest zgodna z włączeniem tego końcowego ;
do makra (z powodów, które wyjaśniłem powyżej: ).
Duplikaty: http://stackoverflow.com/questions/923822/ i http://stackoverflow.com/questions/154136/ oraz http://stackoverflow.com/questions/257418/ – sth
W rzeczywistości istnieje inny sposób popraw to. ({...}) może zrobić to samo, co zrobić {} podczas (0). Ref: http://www.bruceblinn.com/linuxinfo/DoWhile.html – Nybble