C multi-linha macro: fazer / tempo (0) vs bloco âmbito [duplicado]
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 \ }
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).