OVH Cloud OVH Cloud

quel interet d'exit()

28 réponses
Avatar
tournevice
salut
Je me demande quel est l'interet d'appeler la fonction exit() plutot que
return.
Par exemple, si j'ai le programme suivant:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
(void) printf("salut\n") ;
return EXIT_SUCCESS ;
}

et celui-ci:

int main(void)
{
(void) printf("salut\n") ;
exit(EXIT_SUCCESS) ;
}
Qu'est-ce que ca change? Je comprend pas tres bien...si quelqu'un peut
m'eclairer. :)
did
--
Toutes des ingrates...
http://www.netbsd.org/fr
http://www.isty-info.uvsq.fr/~rumeau/fclc/

10 réponses

1 2 3
Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', tournevice wrote:

salut
Je me demande quel est l'interet d'appeler la fonction exit() plutot que
return.
Par exemple, si j'ai le programme suivant:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
(void) printf("salutn") ;
return EXIT_SUCCESS ;
}

et celui-ci:

int main(void)
{
(void) printf("salutn") ;
exit(EXIT_SUCCESS) ;
}
Qu'est-ce que ca change? Je comprend pas tres bien...si quelqu'un peut
m'eclairer. :)


Il est clair que dans main(), le gain est faible!

Par contre, il peut être nécessaire d'avoir une 'sortie de secours' en plein
milieu de l'exécution.

Personellement, j'utilise exit() dans mon 'ASSERT()' maison, qui permet une
sortie plus propre que le assert() standard sur ma plateforme de debug.

A part ça, je ne l'utilise pas.

Extrait de ma bibliothèque perso:

#ifndef SYS_H
#define SYS_H
/* sys.h */

void SYS_assertfail (char const *exp
,char const *file
,int line);

#ifndef NDEBUG
#define ASSERT(a)
do
{
(a) ? (void)0 : SYS_assertfail (#a
, __FILE__
, __LINE__
);
}
while (0)
#else
#define ASSERT(a) ((void)0)
#endif


#endif /* SYS_H */


/* sys.c */
/* ---------------------------------------------------------------------
SYS_assertfail()
---------------------------------------------------------------------
fonction de sortie de la macro ASSERT()
---------------------------------------------------------------------
I:
O:
--------------------------------------------------------------------- */
void SYS_assertfail (char const *exp
,char const *file
,int line)
{
fprintf (stderr, MODULE "assertion '%s' failed at %s:%un"
,(char const *) exp
,(char const *) file
,(unsigned) line
);
fprintf (stderr, MODULE "*** EXIT ***n");
exit (EXIT_FAILURE);
}

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Vincent Lefevre
Dans l'article ,
tournevice écrit:

[exit() vs return dans main]
Qu'est-ce que ca change? Je comprend pas tres bien...si quelqu'un peut
m'eclairer. :)


Ça change surtout pour les implémentations freestanding, pour
lesquelles il n'y a pas forcément de exit() (même s'il y a un
main() avec le même prototype).

Pour les implémentations hébergées, c'est équivalent:

5.1.2.2.3 Program termination

[#1] If the return type of the main function is a type
compatible with int, a return from the initial call to the
main function is equivalent to calling the exit function
with the value returned by the main function as its
argument;9) reaching the } that terminates the main function
returns a value of 0. If the return type is not compatible
with int, the termination status returned to the host
environment is unspecified.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/> - 100%
validated (X)HTML - Acorn Risc PC, Yellow Pig 17, Championnat International
des Jeux Mathématiques et Logiques, TETRHEX, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA

Avatar
Bruno Desthuilliers
tournevice wrote:
salut
Je me demande quel est l'interet d'appeler la fonction exit() plutot que
return.
Par exemple, si j'ai le programme suivant:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
(void) printf("salutn") ;
return EXIT_SUCCESS ;
}

et celui-ci:

int main(void)
{
(void) printf("salutn") ;
exit(EXIT_SUCCESS) ;
}
Qu'est-ce que ca change? Je comprend pas tres bien...si quelqu'un peut
m'eclairer. :)


Bin... dans main(), effectivement, c'est pas flagrant.

Maintenant, mets un exit() dans une fonction appelée par une fonction
appelée par une fonction appelée par une fonction appelée par une
fonction appelée par une fonction appelée par une fonction appelée par
une fonction appelée par une fonction appelée par une fonction appelée
par main(), et ça te semblera - peut-être, éventuellement - utile, au
moins en cas de pépin majeur et irrémédiable.

did
did what ?-)


Bruno

Avatar
Manu
Emmanuel Delahaye wrote:

void SYS_assertfail (char const *exp
,char const *file
,int line);

#ifndef NDEBUG
#define ASSERT(a)
do
{
(a) ? (void)0 : SYS_assertfail (#a
, __FILE__
, __LINE__
);
}
while (0)
#else
#define ASSERT(a) ((void)0)
#endif


Quel est l'interêt de mettre une boucle do { ... } while(0) ?
Est-ce que la définition d'un bloc en plein milieu de code est interdite
par le standard ou bien est-ce parce que certains compilateurs ne
l'accepte pas ?

De même la construction (a)?b:c est-elle vraiment plus rapide qu'un
if-else avec les compilateurs actuels faisant de l'optimisation ?
Ca me fait penser à cet boucle :
for(i=0; i < n; ++i) { ... }
où le prof nous disait qu'il parassait que de mettre ++i générait un
code plus rapide que la même boucle avec i++... Et j'ai attendu ça de la
bouche d'autre personne. Alors, légende ou bien était-ce vrai à l'époque
où les compilateurs n'optimisaient pas bien ?
Je vais faire quelques tests, mais si quelque'un avait une explication
je suis assez interessé...

Merci.

-=( manu )=-

Avatar
Vincent Lefevre
Dans l'article <bfg2g9$bqi$,
Manu écrit:

Emmanuel Delahaye wrote:

void SYS_assertfail (char const *exp
,char const *file
,int line);

#ifndef NDEBUG
#define ASSERT(a)
do
{
(a) ? (void)0 : SYS_assertfail (#a
, __FILE__
, __LINE__
);
}
while (0)
#else
#define ASSERT(a) ((void)0)
#endif


Quel est l'interêt de mettre une boucle do { ... } while(0) ?


Aucun, il me semble, et c'est AMHA fortement déconseillé, car on
ne peut plus faire d'assertion partout où on voudrait.

De même la construction (a)?b:c est-elle vraiment plus rapide qu'un
if-else avec les compilateurs actuels faisant de l'optimisation ?


Le gros avantage de a?b:c est que c'est une expression, donc
réutilisable dans des expressions (ce qui n'est pas le cas du
if-else).

Ca me fait penser à cet boucle :
for(i=0; i < n; ++i) { ... }
où le prof nous disait qu'il parassait que de mettre ++i générait un
code plus rapide que la même boucle avec i++...


C'est n'importe quoi.

Et j'ai attendu ça de la bouche d'autre personne. Alors, légende ou
bien était-ce vrai à l'époque où les compilateurs n'optimisaient pas
bien ?


Ne pas être capable d'optimiser à ce niveau, c'est nul. Et puis
pour les compilo qui n'optimisent pas, il n'y a pas de raison pour
que l'une forme soit systématiquement plus rapide que l'autre.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/> - 100%
validated (X)HTML - Acorn Risc PC, Yellow Pig 17, Championnat International
des Jeux Mathématiques et Logiques, TETRHEX, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA


Avatar
Laurent Wacrenier
Emmanuel Delahaye écrit:
Personellement, j'utilise exit() dans mon 'ASSERT()' maison, qui permet une
sortie plus propre que le assert() standard sur ma plateforme de debug.


abort() n'est pas plus approprié ?

Avatar
Laurent Wacrenier
Vincent Lefevre <vincent+ écrit:
for(i=0; i < n; ++i) { ... }
où le prof nous disait qu'il parassait que de mettre ++i générait un
code plus rapide que la même boucle avec i++...


C'est n'importe quoi.

Et j'ai attendu ça de la bouche d'autre personne. Alors, légende ou
bien était-ce vrai à l'époque où les compilateurs n'optimisaient pas
bien ?


Ne pas être capable d'optimiser à ce niveau, c'est nul. Et puis
pour les compilo qui n'optimisent pas, il n'y a pas de raison pour
que l'une forme soit systématiquement plus rapide que l'autre.


Certains processeurs peuvent avoir des instructions spécifiques pour
faire ++i et i-- afin de gérer une pile mais n'ont pas les
instructions dans l'autre sens. D'autres processeurs peuvent les avoir
uniquement dans l'autre sens. L'optimiseur du compilateur est chargé
de trouver la meilleure combinaison.


Avatar
Horst Kraemer
On Mon, 21 Jul 2003 08:50:48 +0200, Manu wrote:

Emmanuel Delahaye wrote:

void SYS_assertfail (char const *exp
,char const *file
,int line);

#ifndef NDEBUG
#define ASSERT(a)
do
{
(a) ? (void)0 : SYS_assertfail (#a
, __FILE__
, __LINE__
);
}
while (0)
#else
#define ASSERT(a) ((void)0)
#endif


Quel est l'interêt de mettre une boucle do { ... } while(0) ?


Qu'on peut écrire

if (x) ASSERT(a);
else foo();

ce qui ne sarait pas possible si on définissait

#define ASSERT(a)
{
(a) ? (void)0 : SYS_assertfail (#a
, __FILE__
, __LINE__
);
}


Avec cette définition on devrait écrire

if (x) ASSERT(a)
else foo();

ce qui fait mal aux yeux ;-)

({...}; est une séquence de deux "statements" dont le second est
vide.)


C'est un vieu astuce qui garantit que

MACRO

n'est pas d'expression et que

MACRO;

est un (seul) "statement".


--
Horst


Avatar
Gabriel Dos Reis
Horst Kraemer writes:

| On Mon, 21 Jul 2003 08:50:48 +0200, Manu wrote:
|
| > Emmanuel Delahaye wrote:
| >
| > > void SYS_assertfail (char const *exp
| > > ,char const *file
| > > ,int line);
| > >
| > > #ifndef NDEBUG
| > > #define ASSERT(a)
| > > do
| > > {
| > > (a) ? (void)0 : SYS_assertfail (#a
| > > , __FILE__
| > > , __LINE__
| > > );
| > > }
| > > while (0)
| > > #else
| > > #define ASSERT(a) ((void)0)
| > > #endif
| >
| > Quel est l'interêt de mettre une boucle do { ... } while(0) ?
|
| Qu'on peut écrire
|
| if (x) ASSERT(a);
| else foo();

Mais on ne peut plus écrire

for (link = start; ASSERT(a), link; link = link->next)
// ...

| ce qui ne sarait pas possible si on définissait
|
| #define ASSERT(a)
| {
| (a) ? (void)0 : SYS_assertfail (#a
| , __FILE__
| , __LINE__
| );
| }

ceci serait possible si on définissait

#define ASSRRT(a)
((a) ? (void)0 : SYS_assertfail (#a, __FILE__, __LINE__))

-- Gaby
Avatar
Vincent Lefevre
Dans l'article <bfgtf4$emri6$,
Bertrand Mollinier Toublet écrit:

Alors d'accord, c'est une super vieille architecture, c'est plus
vraiment utilise (meme les applis embarques utilisent des PowerPC et
autres SPARCs maintenant), mais que ++i produise du code plus rapide
que i++ c'est pas n'importe quoi. C'est juste vieux et perime.


++i produit du code plus rapide sur *une* machine particulière.
Sur une autre machine avec un compilo aussi mauvais, ça peut être
l'inverse. Maintenant, si c'est juste pour aller plus rapide sur
une machine particulière avec de telles trivialités, je te
conseillerais de programmer en assembleur.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/> - 100%
validated (X)HTML - Acorn Risc PC, Yellow Pig 17, Championnat International
des Jeux Mathématiques et Logiques, TETRHEX, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA

1 2 3