C multi-line makro: do/while(0) vs scope block [duplikat]
Możliwe duplikaty:
jaki jest pożytek z do while(0) gdy definiujemy makro?
dlaczego w makrach C/C++ występują czasami bezsensowne wyrażenia do/while I if/else?
do { ... } while (0) do czego to służy?
Widziałem kilka wielowierszowych makr C, które są zawinięte wewnątrz pętli do / while(0) jak:
#define FOO \ do { \ do_stuff_here \ do_more_stuff \ } while (0)
Jakie są korzyści (jeśli istnieją) z pisania kodu w ten sposób, a nie za pomocą podstawowego blok:
#define FOO \ { \ do_stuff_here \ do_more_stuff \ }
1 answers
Http://bytes.com/groups/c/219859-do-while-0-macro-substitutions
Andrey Tarasevich:
Cała idea użycia wersji 'do / while' polega na stworzeniu makra, które będzie rozwiń do instrukcji regularnej, a nie do instrukcji złożonej. To jest wykonane w celu ujednolicenia użycia makr w stylu funkcyjnym z korzystanie ze zwykłych funkcji we wszystkich kontekstach.
Rozważ następujący szkic kodu
if (<condition>)
foo(a);
else
bar(a);
Gdzie' foo 'i' bar ' są zwyczajne funkcje. Teraz wyobraź sobie, że jak zastąpić funkcję 'foo' makrem o powyższej naturze
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
Teraz, jeśli Twoje makro jest zdefiniowane zgodnie z drugim podejściem (tylko '{' i '}') Kod nie będzie już kompilowany, ponieważ 'true' gałąź ' if ' jest teraz reprezentowana przez wyrażenie złożone. A kiedy ty Wstaw'; 'po tym złożonym oświadczeniu zakończyłeś całe'if' polecenie, tym samym wywołując gałąź 'else' (stąd błąd kompilacji).
One way to popraw ten problem to pamiętaj, aby nie umieszczać '; ' po makro "wywołania"
if (<condition>)
CALL_FUNCS(a)
else
bar(a);
To skompiluje się i będzie działać zgodnie z oczekiwaniami, ale nie jest to jednolite. Na bardziej eleganckim rozwiązaniem jest upewnienie się, że makro rozszerza się do zwykłego oświadczenie, a nie złożone. Jednym ze sposobów osiągnięcia tego celu jest zdefiniowanie makro w następujący sposób
#define CALL_FUNCS(x) \
do { \
func1(x); \
func2(x); \
func3(x); \
} while (0)
Teraz ten kod
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
Skompiluje się bez żadnych problemów.
Jednak zwróć uwagę na małą, ale ważną różnicę między moim definicja
z CALL_FUNCS
i pierwszą wersję w Twojej wiadomości. Nie włożyłem
;
po } while (0)
. Umieszczenie ;
na końcu tej definicji
natychmiast pokonałby cały sens używania "do / while" I sprawił, że
to makro jest prawie równoważne z wersją złożoną.
Nie wiem dlaczego autor kodu, który podałeś w oryginale
wiadomość umieść to ;
po while (0)
. W tej formie oba warianty są
odpowiednik. Cała idea używania wersji 'do / while' nie jest na
załączyć ten końcowy ;
do makra (z powodów które wyjaśniłem
powyżej).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-26 21:52:09