Pergunta

Duplicatas possíveis:
Qual é a utilidade de fazer enquanto (0) quando definimos uma macro?
Por que há, por vezes, sentido do / while e if / else em C / C ++ macros?
do {...} while (0), o que é bom para?

Eu vi algumas macros C multi-linha que são enrolados dentro de um fazer / while (0) loop como:

#define FOO \
  do { \
    do_stuff_here \
    do_more_stuff \
  } while (0)

Quais são os benefícios (se houver) de escrever o código dessa forma em vez de usar um bloco básico:

#define FOO \
  { \
    do_stuff_here \
    do_more_stuff \
  }
Foi útil?

Solução

http://bytes.com/groups/c/ 219859-do-while-0-macro-substituições

Andrey Tarasevich:

A idéia de usar 'fazer / while' versão é fazer uma macro que irá expandir-se para uma declaração regular, não em uma instrução composta. Isto é feito, a fim de fazer o uso de macros de estilo função uniforme com a uso de funções comuns em todos os contextos.

Considere o seguinte código esboço

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

onde 'foo' e 'bar' são funções comuns. Agora imagine que você tinha como para substituir a função 'foo' com uma macro da natureza acima

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

Agora, se sua macro é definido de acordo com a segunda abordagem (Apenas '{' e '}') o código já não compilar, porque o 'verdadeiro' ramo do 'se' é agora representada por uma instrução composta. E quando você colocar uma ';' após esta instrução composta, você terminou o todo 'se' declaração, orfandade, assim, o ramo 'else' (daí o erro de compilação).

Uma maneira de corrigir este problema é lembrar de não colocar ';' depois de macro "invocações"

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

Isto irá compilar e trabalho como esperado, mas isso não é uniforme. o solução mais elegante é ter certeza de que macro expandir em um regular afirmação, não em um composto. Uma maneira de conseguir isso é para definir a macro da seguinte maneira

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

Agora este código

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

irá compilar sem problemas.

No entanto, note que o pequeno, mas importante diferença entre a minha definição de CALL_FUNCS ea primeira versão em sua mensagem. Eu não coloquei um ; após } while (0). Colocar um ; no final dessa definição imediatamente derrotar toda a ponto de usar 'fazer / while' e fazer que macro praticamente equivalente à versão composto comunicado.

Eu não sei por que o autor do código que você citou em sua origem mensagem de colocar isso ; após while (0). Nesta forma ambas as variantes são equivalente. A idéia por trás usando 'fazer / while' versão não é a incluir este ; final no macro (pelas razões que expliquei acima).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top