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 \
  }
Author: Community, 2009-07-01

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).

 233
Author: caskey,
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