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 ;)
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 :
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 ;)
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
"Michel Decima" a écrit dans le message de 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
"Michel Decima" <michel.decima@orange-ft.com> a écrit dans le message de
news: gbdka7$89c$1@news.rd.francetelecom.fr...
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
"Michel Decima" a écrit dans le message de 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
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é.
En news:gbd3gl$f2c$1@news.davenulle.org, 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é.
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-
On 24 sep, 16:34, Pierre Maurette wrote:
Pourquoi pas simplement: #define FOOBAR() {foo(); bar();}
Pfff... Sujet achi épuisé. Tu en es encore là ?
C'est pour forcer l'usage du ';'
On 24 sep, 16:34, Pierre Maurette <maurettepie...@wanadoo.fr> wrote:
Pourquoi pas simplement:
#define FOOBAR() {foo(); bar();}