163 votes

Dois-je renvoyer EXIT_SUCCESS ou 0 à partir de main() ?

C'est une question simple, mais je continue à voir des réponses contradictoires : la routine principale d'un programme C++ doit-elle retourner 0 o EXIT_SUCCESS ?

#include <cstdlib>
int main(){return EXIT_SUCCESS;}

o

int main(){return 0;}

Est-ce que c'est exactement la même chose ? Est-ce que EXIT_SUCCESS ne peut être utilisé qu'avec exit() ?

Je pensais EXIT_SUCCESS serait une meilleure option parce que d'autres logiciels pourraient considérer zéro comme un échec, mais j'ai également entendu dire que si vous renvoyez 0 le compilateur est capable de le changer en une valeur différente de toute façon.

0 votes

Cela répond-il à votre question ? stackoverflow.com/questions/1188335/

2 votes

Cette réponse à propos du C90 paraphrase la norme -- 0 y EXIT_SUCCESS sont toutes deux interprétées comme des succès.

1 votes

Je vais répondre ici car je pense que quelqu'un d'autre lira ce document à l'avenir. Fondamentalement, il existe de nombreux paradigmes sur ce à quoi ressemble un "C correct". Certains paradigmes préfèrent utiliser des littéraux plutôt que des macros, par exemple, au lieu de passer NULL comme argument, ils peuvent passer (const char *)0 pour indiquer que ce n'est pas seulement un null, mais que si ce n'était pas null, ce devrait être un pointeur de caractère constant. D'autres paradigmes préfèrent être agnostiques quant aux types et, en utilisant des macrotypes, ils peuvent éviter de devoir modifier leur base de code lorsque les choses changent radicalement. Par exemple, de nombreux -

196voto

Keith Thompson Points 85120

EXIT_FAILURE soit dans une déclaration de retour dans main ou en tant qu'argument pour exit() est le seul moyen portable d'indiquer un échec dans un programme C ou C++. exit(1) peut effectivement signaler une terminaison réussie sur VMS, par exemple.

Si vous comptez utiliser EXIT_FAILURE lorsque votre programme échoue, alors vous pourriez aussi bien utiliser EXIT_SUCCESS quand il réussit, juste par souci de symétrie.

D'autre part, si le programme ne signale jamais l'échec, vous pouvez utiliser soit 0 o EXIT_SUCCESS . Les deux sont garantis par la norme pour signaler la réussite de l'opération. (Il est à peine possible que EXIT_SUCCESS pourrait avoir une valeur autre que 0, mais elle est égale à 0 sur toutes les implémentations dont j'ai entendu parler).

Utilisation de 0 a le petit avantage que vous n'avez pas besoin de #include <stdlib.h> en C, ou #include <cstdlib> en C++ (si vous utilisez un fichier return plutôt que d'appeler exit() ) - mais pour un programme d'une taille significative, vous allez inclure stdlib directement ou indirectement de toute façon.

D'ailleurs, dans le C à partir de la norme de 1999, et dans toutes les versions du C++, jusqu'à la fin de l'année 1999, le système de gestion de l'information a été modifié. main() fait un return 0; de toute façon, vous n'aurez peut-être pas besoin d'utiliser l'un ou l'autre 0 o EXIT_SUCCESS de manière explicite. (Mais au moins en C, je considère qu'une version explicite de return 0; pour avoir un meilleur style).

(Quelqu'un a posé une question sur OpenVMS. Je ne l'ai pas utilisé depuis longtemps, mais si je me souviens bien, les valeurs d'état impaires indiquent généralement un succès, tandis que les valeurs paires indiquent un échec. L'implémentation C fait correspondre 0 à 1 de sorte que return 0; indique une terminaison réussie. Les autres valeurs sont transmises inchangées, donc return 1; indique également une terminaison réussie. EXIT_FAILURE aurait une valeur paire non nulle).

0 votes

@KeithThompson Pourriez-vous clarifier votre réponse en ce qui concerne VMS (OpenVMS ?). Il n'est pas clair la relation EXIT_SUCCESS / EXIT_FAILURE avec 0 et 1. J'expliquerais plutôt les valeurs impaires/paires.

0 votes

@malat : Utilisez-vous réellement VMS ?

0 votes

Non, je ne l'ai jamais utilisé. Je cherchais une réponse canonique, puisque wikipedia utilisait une réponse de type libellé différent .

31voto

Alok Save Points 115848

Cela n'a pas d'importance. Les deux sont les mêmes.

Citations de la norme C++ :

Si la valeur de status est zéro ou EXIT_SUCCESS, une forme définie par l'implémentation du status successful termination est retournée.

17 votes

Cela n'a pas d'importance pour le compilateur, mais cela peut en avoir une pour le style.

2 votes

@celtschk : La question du style est basée sur la perception, c'est-à-dire qu'elle n'est pas normalisée, donc elle ne compte pas comme une différence.

3 votes

Il n'y a aucune garantie que EXIT_SUCCESS == 0 . D'un autre côté, il n'y a aucune raison pour que ce ne soit pas le cas.

16voto

James Points 5137

Le 0 est, par définition, un chiffre magique. EXIT_SUCCESS est presque universellement égal à 0, et c'est heureux. Alors pourquoi ne pas simplement renvoyer/ sortir 0 ?

exit(EXIT_SUCCESS) ; a une signification très claire.

exit(0) ; d'autre part, est contre-intuitif à certains égards. Une personne qui n'est pas familière avec le comportement de l'interpréteur de commandes pourrait supposer que 0 == faux == mauvais, tout comme toutes les autres utilisations de 0 en C. Mais non - dans ce cas particulier, 0 == succès == bon. Pour la plupart des développeurs expérimentés, ce ne sera pas un problème. Mais pourquoi faire trébucher le nouveau pour absolument aucune raison ?

tl;dr - s'il existe une constante définie pour votre nombre magique, il n'y a presque jamais de raison de ne pas utiliser la constante en premier lieu. C'est plus facile à rechercher, souvent plus clair, etc. et cela ne vous coûte rien.

2 votes

Je pense que vos commentaires sur les gens qui s'attendent à ce que 0 soit automatiquement mauvais ne sont pas pertinents. De très nombreuses API utilisent 0 pour le succès, et non-0 pour l'échec, même dans la stdlib. Par exemple, la stdlib ( fclose() , setvbuf() ...), POSIX ( listen() , pthread_create() , pipe() ...), et bien d'autres, beaucoup de d'autres bibliothèques (par exemple, OpenGL [ glGetError() ], zlib [ deflate() / inflate() /...], SDL [ SDL_CreateWindowAndRenderer() /...], et plus encore).

3 votes

Bien sûr, il existe d'autres cas où le 0 est utilisé pour le "succès", mais il a raison de dire que cela prête à confusion.

12voto

Emilio Garavaglia Points 9189

Il s'agit d'une histoire sans fin qui reflète les limites (un mythe) de "l'interopérabilité et la portabilité par-dessus tout".

Ce que le programme doit renvoyer pour indiquer un "succès" doit être défini par celui qui reçoit la valeur (le système d'exploitation ou le processus qui a invoqué le programme) et non par une spécification du langage.

Mais les programmeurs aiment écrire du code d'une "manière portable" et donc ils inventent leur propre modèle pour le concept de "système d'exploitation" définissant des valeurs symboliques à retourner.

Maintenant, dans un scénario many-to-many (où de nombreux langages servent à écrire des programmes pour de nombreux systèmes), la correspondance entre la convention du langage pour le "succès" et celle du système d'exploitation (que personne ne peut garantir être toujours la même) devrait être gérée par l'implémentation spécifique d'une bibliothèque pour une plate-forme cible spécifique.

Mais - malheureusement - ces concepts n'étaient pas aussi clairs à l'époque où le langage C a été déployé (principalement pour écrire le noyau UNIX), et des gigagrammes de livres ont été écrits en disant "retour 0 signifie succès", puisque c'était vrai sur le système d'exploitation de l'époque ayant un compilateur C.

Dès lors, aucune normalisation claire n'a jamais été faite sur la manière dont une telle correspondance devait être traitée. Le C et le C++ ont leur propre définition des "valeurs de retour" mais personne n'a fourni une traduction correcte pour les systèmes d'exploitation (ou mieux : aucune documentation de compilateur n'en parle). 0 signifie le succès si c'est vrai pour UNIX - LINUX et - pour des raisons indépendantes - pour Windows aussi, et cela couvre 90% des "ordinateurs grand public" existants, qui - dans la plupart des cas - ne tiennent pas compte de la valeur de retour (ainsi nous pouvons discuter pendant des décennies, mais personne ne le remarquera jamais !)

Dans ce scénario, avant de prendre une décision, posez-vous ces questions : - Suis-je intéressé à communiquer quelque chose à mon interlocuteur sur mon existant ? (Si je renvoie toujours 0 ... il n'y a pas d'indice derrière tout cela). - Mon interlocuteur a-t-il des conventions concernant cette communication ? (Notez qu'une valeur unique n'est pas une convention : cela ne permet aucune représentation de l'information).

Si les deux réponses sont négatives, la bonne solution est probablement de ne pas écrire du tout l'instruction de retour principale. (Et laisser le compilateur décider, en fonction de la cible sur laquelle il travaille).

Si aucune convention n'est en place 0=réussite répondent à la plupart des situations (et l'utilisation de symboles peut être problématique, s'ils introduisent une convention).

Si des conventions sont en place, assurez-vous d'utiliser des constantes symboliques qui sont cohérentes avec elles (et assurez la cohérence des conventions, et non la cohérence des valeurs, entre les plateformes).

4voto

Phonon Points 6751

Une fois que vous commencez à écrire du code qui peut retourner une myriade d'états de sortie, vous commencez #define tous. Dans ce cas EXIT_SUCCESS a un sens dans le contexte de ne pas être un " nombre magique ". Cela rend votre code plus lisible parce que tous les autres codes de sortie seront EXIT_SOMETHING . Si vous écrivez simplement un programme qui reviendra quand il aura terminé, return 0 est valide, et probablement encore plus propre car elle suggère qu'il n'y a pas de structure de code de retour sophistiquée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X