macro do { } while(0)

Le
Patrick Lamaizière
'jour,

Quel est l'intérêt profond de déclarer des macros en do { } while (0) ?

Par exemple dans l'idée:

#define PRINT(x) do {
printf(x);
} while (0)

Merci.
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Michel Decima
Le #17324781
Patrick Lamaizière a écrit :
'jour,

Quel est l'intérêt profond de déclarer des macros en do { } while (0) ?

Par exemple dans l'idée:

#define PRINT(x) do {
printf(x);
} while (0)



Eviter les problemes subtils lorsque la macro est appellee
dans un if/else, sans accolades :

void foo() { printf( "foo" ) ; }
void bar() { printf( "bar" } ; }

#define FOOBAR() do { foo(); bar(); } while( 0 )

int main( int argc, char** argv )
{
if ( argc > 1 ) FOOBAR() ;
return 0 ;
}

Regarde le comportement avec et sans le do/while (et c'est encore
plus drole si on rajoute un else)
Pierre Maurette
Le #17327131
Michel Decima, le 24/09/2008 a écrit :
Patrick Lamaizière a écrit :
'jour,

Quel est l'intérêt profond de déclarer des macros en do { } while (0) ?

Par exemple dans l'idée:

#define PRINT(x) do {
printf(x);
} while (0)



Eviter les problemes subtils lorsque la macro est appellee
dans un if/else, sans accolades :

void foo() { printf( "foo" ) ; }
void bar() { printf( "bar" } ; }

#define FOOBAR() do { foo(); bar(); } while( 0 )

int main( int argc, char** argv )
{
if ( argc > 1 ) FOOBAR() ;
return 0 ;
}

Regarde le comportement avec et sans le do/while (et c'est encore
plus drole si on rajoute un else)



Pourquoi pas simplement:
#define FOOBAR() {foo(); bar();}
?

--
Pierre Maurette
Michel Decima
Le #17327481
Pierre Maurette a écrit :
Michel Decima, le 24/09/2008 a écrit :
Patrick Lamaizière a écrit :
'jour,

Quel est l'intérêt profond de déclarer des macros en do { } while (0) ?

Par exemple dans l'idée:

#define PRINT(x) do {
printf(x);
} while (0)



Eviter les problemes subtils lorsque la macro est appellee
dans un if/else, sans accolades :

void foo() { printf( "foo" ) ; }
void bar() { printf( "bar" } ; }

#define FOOBAR() do { foo(); bar(); } while( 0 )

int main( int argc, char** argv )
{
if ( argc > 1 ) FOOBAR() ;
return 0 ;
}

Regarde le comportement avec et sans le do/while (et c'est encore
plus drole si on rajoute un else)



Pourquoi pas simplement:
#define FOOBAR() {foo(); bar();}
?



Bonne question.

A premiere vue, la version do/while necessite l'ajout d'un
point-virgule, pas la version "simple". Je ne sais pas si
c'est suffisant, mais dans la pratique j'ai souvent vu la
premiere, et je crois jamais la deuxieme, mais cet avis
est forcement biaisé : la forme bizarre de la version
do/while fait qu'on la retient mieux que l'autre ;)
Charlie Gordon
Le #17327621
"Michel Decima" news: gbdka7$89c$
Pierre Maurette a écrit :

Pourquoi pas simplement:
#define FOOBAR() {foo(); bar();}
?



Bonne question.

A premiere vue, la version do/while necessite l'ajout d'un
point-virgule, pas la version "simple". Je ne sais pas si
c'est suffisant, mais dans la pratique j'ai souvent vu la
premiere, et je crois jamais la deuxieme, mais cet avis
est forcement biaisé : la forme bizarre de la version
do/while fait qu'on la retient mieux que l'autre ;)



Cette forme ne fonctionne pas dans le cas suivant:

if (toto)
FOOBAR();
else
FOOFOO();

en effet on a l'expansion suivante:

if (toto)
{foo(); bar();};
else
FOOFOO();

qui est un erreur de syntaxe parce que ``{xxx};'' cela fait 2 statements
alors que ``do{xxx}while(0);'' n'en fait qu'un.

Moralité: les macros c'est du poison, voici quelques règle de cuisine:

* il faut toujours parentheser les arguments dans l'expansion, et
l'expansion elle-meme si c'est une expression,
* il faut faire en sorte que l'expansion soit une expression ou un statement
unique sans ; final, en utilisant eventuellement l'astuce do/while(0)
* il faut evaluer les arguments une fois et une seule dans l'expansion,
* dans le cas ou la regle ci-dessus est impraticable, il faut que le nom de
la macro soit en majuscules.
* dans les cas ou c'est possible, on preferera utiliser une fonction static
inline

--
Chqrlie
Antoine Leca
Le #17328121
En news:gbd3gl$f2c$, Patrick Lamaizière va escriure:
Quel est l'intérêt profond de déclarer des macros en do { } while (0)?



Pouvoir mettre un appel de la dite macro comme instruction unique
(c'est-à-dire SANS {}) comme sujet d'une construction if()/while()/for()
etc.

C'est en fait l'équivalent pour les instructions de la paire de parenthèses
englobantes qui est (hautement) recommandée pour les expressions dans les
macros.


Par exemple dans l'idée:

#define PRINT(x) do {
printf(x);
} while (0)



Aucun intérêt réel ici, puisqu'il n'y a pas d'expansion¹.
Mais si tu considères le peu différent
#define PRINT(x) do {
fprintf(journal, x);
printf(x);
} while (0)

cela permet d'écrire ensuite

if( tout_va_bien(toto) )
PRINTX(toto);

sans introduire un bogue très vicieux, qui se manifestera (probablement par
un SSIGSEGV ou similaire) seulement le jour où tout_ne_va_pas_bien...


Antoine
____________
¹: sauf dans le cas puant où en fait printf() est une macro mal définie
comme
#define printf(x) machine(x); truc(x);
Mais bon, je néglige parce que un tel truc est du domaine de la pourriture
impossible à rencontrer dans la réalité.
-ed-
Le #17342861
On 24 sep, 16:34, Pierre Maurette
Pourquoi pas simplement:
#define FOOBAR()  {foo(); bar();}



Pfff... Sujet achi épuisé. Tu en es encore là ?

C'est pour forcer l'usage du ';'
Publicité
Poster une réponse
Anonyme