Andrey Tarasevich fournit l'explication suivante :
- Sur Google Groupes
- Sur bytes.com
[Des changements mineurs ont été apportés au formatage. Les annotations entre parenthèses ont été ajoutées entre crochets. []
].
L'idée générale de l'utilisation de la version 'do/while' est de créer une macro qui va qui se développera en une instruction normale, et non en une instruction composée. Ceci est afin d'uniformiser l'utilisation des macros de type fonction avec l'utilisation des l'utilisation de fonctions ordinaires dans tous les contextes.
Considérons l'esquisse de code suivante :
if (<condition>)
foo(a);
else
bar(a);
donde foo
y bar
sont des fonctions ordinaires. Imaginez maintenant que vous souhaitez souhaitez remplacer la fonction foo
avec une macro de la nature ci-dessus [nommée CALL_FUNCS
] :
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
Maintenant, si votre macro est définie selon la deuxième approche (juste {
y }
) le code ne compilera plus, car la branche 'true' (vraie) de if
est maintenant représentée par une déclaration composée. Et lorsque vous mettez un ;
après cette déclaration composée, vous avez terminé l'ensemble if
, ce qui rend orphelin le else
(d'où l'erreur de compilation).
Une façon de corriger ce problème est de se rappeler de ne pas mettre ;
après macro "invocations" :
if (<condition>)
CALL_FUNCS(a)
else
bar(a);
Cela compilera et fonctionnera comme prévu, mais ce n'est pas uniforme. La solution plus élégante solution la plus élégante est de s'assurer que la macro se développe dans une ordinaire, et non dans une déclaration composée. Une façon d'y parvenir est de définir la macro comme suit :
#define CALL_FUNCS(x) \
do { \
func1(x); \
func2(x); \
func3(x); \
} while (0)
Maintenant ce code :
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
compilera sans problème.
Cependant, notez la petite mais importante différence entre ma définition de CALL_FUNCS
et la première version dans votre message. Je n'ai pas mis de ;
après } while (0)
. Mettre un ;
à la fin de cette définition l'intérêt d'utiliser 'do/while' et rendrait cette macro pratiquement cette macro est pratiquement équivalente à la version de l'instruction composée.
Je ne sais pas pourquoi l'auteur du code que vous avez cité dans votre message original message original a mis ceci ;
après while (0)
. Sous cette forme, les deux variantes sont équivalentes. L'idée derrière l'utilisation de la version 'do/while' est de ne pas d'inclure cette dernière ;
dans la macro (pour les raisons que j'ai expliquées ci-dessus).
5 votes
Duplicata : stackoverflow.com/questions/923822 y stackoverflow.com/questions/154136 y stackoverflow.com/questions/257418
0 votes
En fait, il existe un autre moyen de faire les choses correctement. ({...}) peut faire la même chose que do {} while(0). Réf : bruceblinn.com/linuxinfo/DoWhile.html
2 votes
@wuxb : le
({...})
construct est une extension de GCC et n'est pas supportée par le standard C de l'ISO.