Qu'est-ce que main() devrait retourner en C et c++?
Quelle est la façon correcte (la plus efficace) de définir la fonction main()
en C et C++ - int main()
ou void main()
- et pourquoi?
Si int main()
puis return 1
ou return 0
?
il y a de nombreux doubles de cette question, y compris:
- quelles sont les signatures valides pour la fonction C
main()
? - le type de retour de
main()
fonction - différence entre
void main()
etint main()
? -
main()
's signature en C++ - Quelle est la déclaration appropriée de
main()
? - pour C++, avec une très bonne réponse en effet. - Styles
main()
fonctions en C - Type de retour de
main()
méthode en C -
int main()
vsvoid main()
in C
Related:
- C++ -
int main(int argc, char **argv)
- C++ -
int main(int argc, char *argv[])
- Est
char *envp[]
comme troisième argument demain()
portable? - la fonction
int main()
doit-elle retourner une valeur dans tous les compilateurs? - pourquoi le type de la fonction
main()
en C et c++ est-il laissé à l'utilisateur pour définir? - pourquoi
int main(){}
compile-t-il? - définitions légales de
main()
dans C++14?
18 réponses
la valeur de retour de main
devrait indiquer comment le programme a quitté. La sortie normale est généralement représentée par une valeur de retour 0 de main
. La terminaison anormale est habituellement signalée par un retour non nul, mais il n'y a pas de norme pour l'interprétation des codes non nuls. Comme d'autres l'ont noté, void main()
est explicitement interdit par la norme C++ et ne devrait pas être utilisé. Les signatures valides C++ main
sont:
int main()
et
int main(int argc, char* argv[])
qui est l'équivalent de
int main(int argc, char** argv)
il est aussi intéressant de noter que dans C++, int main()
peut être laissé sans valeur de retour à laquelle il renvoie 0 par défaut. Cela est également vrai dans le cas d'un programme C99. La question de savoir si le retour 0 doit être omis ou non est discutable. Le nombre de signatures valides pour le programme C est beaucoup plus élevé.
en outre, l'efficacité n'est pas un problème avec la fonction main
. Il ne peut être entré et laissé qu'une seule fois (en marquant le début et la fin du programme) selon la norme C++. Pour C, le cas est différent et la réimpression de main()
est autorisée, mais devrait probablement être évitée.
la réponse acceptée semble être ciblée Pour C++, donc j'ai pensé que je pourrais ajouter une réponse qui se rapporte à C, et cela diffère à quelques égards.
ISO / CEI 9899: 1989 (C90):
main()
doit être déclaré comme suit:
int main(void)
int main(int argc, char **argv)
ou l'équivalent. Par exemple, int main(int argc, char *argv[])
est équivalent à la seconde. De plus, le type de retour int
peut être omis car il s'agit d'un défaut.
si une mise en œuvre le permet, main()
peut être déclaré d'une autre manière, mais cela rend la mise en œuvre du programme définie, et plus strictement conforme.
la norme définit trois valeurs de retour qui sont strictement conformes (c'est-à-dire qui ne dépendent pas d'un comportement défini par la mise en œuvre): 0
et EXIT_SUCCESS
pour une fin réussie, et EXIT_FAILURE
pour une fin non réussie. Toutes les autres valeurs sont non standard et la mise en œuvre définies. main()
doit avoir une mention explicite return
à la fin pour éviter un comportement non défini.
enfin, il n'y a rien de mal, du point de vue des normes, à appeler main()
d'un programme.
ISO / CEI 9899: 1999 (C99):
pour C99, tout est comme ci-dessus sauf:
- le type de retour
int
ne peut être omis. - vous pouvez omettre la déclaration de retour de
main()
. Si vous le faites, etmain()
terminé, il ya un implicitereturn 0
.
Standard C - Environnement Hébergé
pour un environnement hébergé (c'est normal), la norme C11 (ISO / IEC 9899: 2011) dit:
5.1.2.2.1 démarrage du programme
la fonction appelée au démarrage du programme s'appelle
main
. La mise en œuvre déclare non prototype pour cette fonction. Il doit être défini avec un type de retourint
et sans paramètre:int main(void) { /* ... */ }
ou avec deux paramètres (appelés ici
argc
etargv
, bien que n'importe quel nom puisse être utilisé, car ils sont locaux à la fonction dans laquelle ils sont déclarés):int main(int argc, char *argv[]) { /* ... */ }
ou l'équivalent; 10) ou d'une autre manière définie par la mise en œuvre.
S'ils sont déclarés, les paramètres de la fonction principale doivent obéir aux règles suivantes: contraintes:
- la valeur de
argc
doit être non négative.argv[argc]
doit être un pointeur nul.- si la valeur de
argc
est supérieure à zéro, les membres du tableauargv[0]
parargv[argc-1]
inclusive doit contenir des pointeurs vers des chaînes, qui sont donnés implémentation-valeurs définies par l'environnement hôte avant le démarrage du programme. Le l'intention est de fournir à l'information de programme déterminée avant le démarrage du programme d'ailleurs dans l'environnement hébergé. Si l'environnement hôte n'est pas capable de fournir des chaînes avec des lettres en majuscules et en minuscules, la mise en œuvre doit s'assurer que les cordes sont reçues en minuscules.- Si la valeur de
argc
est supérieure à zéro, la chaîne pointée parargv[0]
représente le nom du programme;argv[0][0]
est le caractère null si le le nom du programme n'est pas disponible dans l'environnement d'accueil. Si la valeur deargc
est plus grand qu'un, les cordes pointées parargv[1]
àargv[argc-1]
représentent les paramètres du programme.- paramètres
argc
etargv
et les chaînes pointées par leargv
tableau sont être modifiables par le programme, et conserver leurs dernières valeurs stockées entre les programmes démarrage et fin du programme.10) ainsi,
int
peut être remplacé par un nom typéf défini commeint
, ou le type deargv
peut être écrit commechar **argv
, et ainsi de suite.
de fin de Programme en C99 ou C11
la valeur retournée de main()
est transmise à l '"environnement" d'une manière définie par la mise en œuvre.
5.1.2.2.3 fin du programme
1 si le type de retour de la fonction
main
est un type compatible avecint
, un retour l'appel initial à la fonctionmain
est équivalent à l'appel de la fonctionexit
avec la valeur renvoyé par la fonctionmain
comme son argument; 11) atteindre le}
qui met fin à lamain
renvoie une valeur de 0. Si le type de retour n'est pas compatible avecint
, le le statut de résiliation retourné à l'environnement hôte n'est pas spécifié.11) conformément au 6.2.4, les durées de vie des objets avec une durée de stockage automatique déclarée en
main
terminée dans le premier cas, même là où ils n'auraient pas dans le second.
notez que 0
est obligatoire en tant que "succès". Vous pouvez utiliser EXIT_FAILURE
et EXIT_SUCCESS
à partir de <stdlib.h>
si vous préférez, mais 0 est bien établi, et est donc 1. Voir aussi codes de sortie supérieurs à 255 - possible? .
dans C89 (et donc dans Microsoft C), il n'y a pas de déclaration sur ce qui se passe si la fonction main()
retourne mais ne spécifie pas de valeur de retour; elle conduit donc à un comportement non défini.
7.22.4.4 le
exit
fonction¶5 Enfin, le contrôle est retourné à l'environnement hôte. Si la valeur de
status
est zéro ouEXIT_SUCCESS
, une forme définie par la mise en œuvre du statut terminaison réussie est retournée. Si la valeur destatus
estEXIT_FAILURE
, une forme définie par la mise en œuvre du statut terminaison infructueuse est retournée. Sinon, le statut retourné est défini par l'implémentation.
Standard C++ Environnement Hébergé
la norme C++11 (ISO / IEC 14882: 2011) dit:
3.6.1 fonction principale [fonction de base.commencer.main]
¶1 Un programme doit contenir une fonction globale appelée principal, qui est le départ du programme. [...]
¶2 Une mise en œuvre ne doit pas précéder la fonction principale. Ce la fonction ne doit pas être surchargé. Il est avoir un type de retour de type int, mais sinon son type est implémentation définie. Toutes les implémentations doit permettre les deux définitions suivantes de main:
int main() { /* ... */ }
et
int main(int argc, char* argv[]) { /* ... */ }
sous cette dernière forme
argc
doit être le nombre d'arguments transmis au programme par l'environnement dans lequel le programme est exécuté. Siargc
est non nul ces arguments doit être fourni enargv[0]
parargv[argc-1]
comme pointeurs vers les caractères initiaux des chaînes multi-octets à terminaison nulle (NTMBSs) (17.5.2.1.4.2) etargv[0]
doit être le pointeur vers le caractère initial D'une NTMBS qui représente nom utilisé pour invoquer le programme ou""
. La valeur deargc
doit être non négative. La valeur deargv[argc]
doit être 0. [ Note: il est recommandé d'ajouter tout autre paramètre (facultatif) aprèsargv
. -fin note ]¶3 la fonction
main
ne doit pas être utilisée dans un programme. Le lien (3.5) demain
est défini par la mise en œuvre. [...]¶5 Une déclaration dans le corps du texte a pour effet de quitter la fonction principale (détruire tout objet avec une durée de stockage) et appelant
std::exit
avec la valeur de retour comme argument. Si le contrôle atteint la fin de main sans rencontrer de déclaration de retour, l'effet est celui de l'exécutionreturn 0;
la norme c++ dit explicitement "il [la fonction principale] doit avoir un type de retour de type int
, mais sinon son type est implémentation définie", et nécessite les deux mêmes signatures que la norme C pour être pris en charge comme options. Ainsi, un ' void main ()' n'est pas directement autorisé par le standard c++, bien qu'il n'y ait rien qu'il puisse faire pour arrêter une implémentation non standard permettant des alternatives. Note ce c++ interdit à l'utilisateur d'appeler main
(mais pas la norme C).
il y a un paragraphe de §18.5 Start and termination dans la norme C++11 qui est identique au paragraphe de §7.22.4.4 la exit
fonction dans la norme C11 (citée ci-dessus), à l'exception d'une note de bas de page (qui documente simplement que EXIT_SUCCESS
et EXIT_FAILURE
sont définis dans <cstdlib>
).
Standard C-Common Extension
classiquement, les systèmes Unix supportent une troisième variante:
int main(int argc, char **argv, char **envp) { ... }
le troisième argument est une liste à terminaison nulle de pointeurs vers les chaînes, dont chacune est une variable d'environnement qui a un nom, un signe égal et une valeur (éventuellement vide). Si vous ne l'utilisez pas, vous pouvez toujours accéder à l'environnement via ' extern char **environ;
". Depuis longtemps, qui n'ont pas d'en-tête qui l'a déclaré, mais la norme POSIX 2008 exige maintenant qu'elle soit déclarée dans <unistd.h>
.
ceci est reconnu par la norme C comme une extension courante, documentée à L'Annexe J:
J. 5.1 arguments D'environnement
¶1 Dans un environnement hébergé, la fonction principale reçoit un troisième argument,
char *envp[]
, qui pointe vers un tableau de pointeurs à terminaison nulle dechar
, chacun de qui pointe vers une corde qui fournit des informations sur l'environnement d'exécution du programme (5.1.2.2.1).
Microsoft C
le Microsoft VS 2010 compilateur est intéressant. Le site Web dit:
la syntaxe de la déclaration pour main est
int main();
ou, facultativement,
int main(int argc, char *argv[], char *envp[]);
alternativement, les fonctions
main
etwmain
peuvent être déclarées comme retournantvoid
(aucune valeur de retour). Si vous déclarez quemain
ouwmain
est nul, vous ne pouvez pas retourner un code de sortie au processus parent ou au système d'exploitation en utilisant un État de retour. Pour retourner un code de sortie lorsquemain
ouwmain
est déclaré commevoid
, vous devez utiliser la fonctionexit
.
il est pas clair pour moi ce qui se passe (quel code de sortie est retourné au parent ou à L'OS) quand un programme avec void main()
sort - et le site Web de MS est silencieux aussi.
fait intéressant, MS ne prescrit pas la version à deux arguments de main()
que les normes C et C++ exigent. Il ne prescrit trois argument forme où le troisième argument est char **envp
, un pointeur vers une liste de variables d'environnement.
la page Microsoft aussi liste d'autres alternatives - wmain()
qui prend des chaînes de caractères larges, et plus encore.
Microsoft Visual Studio 2005 version de cette page ne pas inscrire void main()
comme une alternative. Les versions de Microsoft Visual Studio 2008 à partir de faire.
Standard C - Autonome De L'Environnement
comme nous l'avons déjà mentionné, les exigences ci-dessus s'appliquent aux environnements hébergés. Si vous travaillez avec un environnement autonome (qui est l'alternative à un environnement hébergé), alors la norme a beaucoup moins à dire. Pour un environnement autonome, la fonction appelée au démarrage du programme n'a pas besoin d'être appelée main
et il n'y a aucune contrainte sur son type de retour. La norme dit:
5.1.2 environnements D'exécution
deux environnements d'exécution sont définis: freestanding et hosted. Dans les deux cas, le démarrage du programme se produit quand une fonction C désignée est appelée par l'exécution environnement. Tous les objets avec une durée de stockage statique doivent être initialisés (mis à leurs valeurs initiales) avant le démarrage du programme. La manière et le moment de cette initialisation ne sont pas précisés. Fin de programme retourne le contrôle à l'environnement d'exécution.
5.1.2.1 Environnement autoportant
dans un environnement autonome (dans lequel L'exécution du programme C peut avoir lieu sans aucun avantage d'un système d'exploitation), le nom et le type de la fonction appelée au démarrage du programme sont implémentation-defined. Toute bibliothèque disponible pour un programme autonome, autre que l'ensemble minimal requis par l'article 4, est définie par la mise en œuvre.
L'effet de fin de programme dans un autoportant l'environnement est mise en œuvre définies.
le renvoi à la conformité à la clause 4 renvoie à ceci:
numéro 5 en se conformant strictement programme ne doit utiliser que les fonctionnalités de la langue et de la bibliothèque spécifiée dans la présente Norme Internationale. 3) il ne doit pas produire de sortie dépendant d'un comportement non spécifié, non défini, ou défini par la mise en œuvre, et ne doit pas dépasser une limite minimale de mise en œuvre.
¶6 les deux formes de mise en œuvre conforme sont hébergé et autonome . Un conforme mise en œuvre hébergée doit accepter tout programme strictement conforme. Un conforme autonomes de mise en œuvre doit accepter tout en se conformant strictement programme dans lequel l'utilisation des fonctions spécifiées dans la la clause de bibliothèque (clause 7) se limite au contenu des en-têtes standards
<float.h>
,<iso646.h>
,<limits.h>
,<stdalign.h>
,<stdarg.h>
,<stdbool.h>
,<stddef.h>
,<stdint.h>
, et<stdnoreturn.h>
. Une implémentation conforme peut avoir des extensions (y compris fonctions supplémentaires de la bibliothèque), à condition qu'ils ne modifient pas le comportement d'un programme strictement conforme. 4)¶7 conforme le programme est un programme acceptable pour une mise en œuvre conforme. 5)
3) un programme strictement conforme peut utiliser des caractéristiques conditionnelles (voir 6.10.8.3) à condition que l'utilisation soit protégée par une directive appropriée de prétraitement d'inclusion conditionnelle utilisant la macro correspondante. Par exemple:
#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */ /* ... */ fesetround(FE_UPWARD); /* ... */ #endif
4) cela implique qu'une la mise en œuvre se réserve pas de désignations autres que celles qui sont explicitement réservés dans la présente Norme Internationale.
5) les programmes strictement conformes sont conçus pour être transférables au maximum parmi les implémentations conformes. Les programmes conformes peuvent dépendre des caractéristiques non portables d'une mise en œuvre conforme.
Il est notable que le seul en-tête requis d'un autoportant environnement en fait définit toutes les fonctions est <stdarg.h>
(et même ceux peuvent être - et sont souvent - juste des macros).
Standard C++ - Autonome De L'Environnement
tout comme la norme C reconnaît à la fois l'environnement hébergé et l'environnement autonome, il en va de même de la norme C++. (Citations de ISO / IEC 14882: 2011.)
1.4 Mise en oeuvre conformité [intro.la conformité]
¶7 deux sortes de les implémentations sont définies: une implémentation hébergée et une implémentation autonome . Pour une mise en œuvre hébergée, cette norme internationale définit l'ensemble des bibliothèques disponibles. Un autoportant la mise en œuvre est une exécution qui peut avoir lieu sans le bénéfice d'un système d'exploitation, et a un ensemble de bibliothèques défini par la mise en œuvre qui inclut certaines bibliothèques de soutien linguistique (17.6.1.3).
¶8 une implémentation conforme peut avoir des extensions (y compris des fonctions supplémentaires de bibliothèque), à condition qu'elles ne modifient pas le comportement d'un programme bien formé. Les implémentations sont nécessaires pour diagnostiquer les programmes que utilisez de telles extensions qui sont mal formées selon cette norme internationale. Cela étant, ils peuvent compiler et exécuter de tels programmes.
¶9 chaque mise en œuvre doit comprendre des documents qui identifient tous les le support conditionnel construit qu'il ne supporte pas et ne définit pas toutes les caractéristiques locales spécifiques. 3
3) cette documentation définit également le comportement défini par la mise en œuvre; Voir 1.9.
17.6.1.3 mises en œuvre autoportantes [conformité]
deux types d'implémentations sont définis: hébergées et autonomes (1.4). Pour une hébergé mise en œuvre, cette norme internationale décrit l'ensemble des en-têtes disponibles.
une implémentation autonome a un ensemble d'en-têtes défini par implémentation. Cet ensemble comprend au moins les en-têtes figurant au Tableau 16.
la version fournie de l'en-tête
<cstdlib>
doit déclarer au moins les fonctionsabort
,atexit
,at_quick_exit
,exit
, etquick_exit
(18.5). Les autres en-têtes liste figurant dans ce tableau doit répondre aux mêmes exigences que pour une mise en œuvre hébergée.Tableau 16 - C++ - têtes pour les implémentations autonomes
Subclause Header(s) <ciso646> 18.2 Types <cstddef> 18.3 Implementation properties <cfloat> <limits> <climits> 18.4 Integer types <cstdint> 18.5 Start and termination <cstdlib> 18.6 Dynamic memory management <new> 18.7 Type identification <typeinfo> 18.8 Exception handling <exception> 18.9 Initializer lists <initializer_list> 18.10 Other runtime support <cstdalign> <cstdarg> <cstdbool> 20.9 Type traits <type_traits> 29 Atomics <atomic>
et si on utilisait int main()
en C?
la norme § 5.1.2.2.1 de la norme C11 montre la notation préférée - int main(void)
- mais il y a aussi deux exemples dans la norme qui montrent int main()
: Paragraphe 6.5.3.4, numéro 8 §6.7.6.3 ¶20 . Maintenant, il est important de noter que les exemples ne sont pas "normatifs"; ils ne sont qu'indicatifs. Si il y a des bugs dans les exemples, ils n'affectent pas directement le texte principal de la norme. Cela dit, elles sont fortement indicatives du comportement attendu, donc si la norme inclut int main()
dans un exemple, elle suggère que int main()
n'est pas interdit, même si ce n'est pas la notation préférée.
6.5.3.4 les
sizeof
et_Alignof
opérateurs...
¶8 Exemple 3 dans cet exemple, la taille d'un tableau de longueur variable est calculée et retournée à partir d'une fonction:
#include <stddef.h> size_t fsize3(int n) { char b[n+3]; // variable length array return sizeof b; // execution time sizeof } int main() { size_t size; size = fsize3(10); // fsize3 returns 13 return 0; }
je crois que main()
devrait retourner soit EXIT_SUCCESS
ou EXIT_FAILURE
. Ils sont définis dans stdlib.h
notez que les standards C et C++ définissent deux types d'implémentations: freestanding et hosted.
-
C90 environnement hébergé
formulaires autorisés 1 :
int main (void) int main (int argc, char *argv[]) main (void) main (int argc, char *argv[]) /*... etc, similar forms with implicit int */
commentaires:
les deux premières sont explicitement indiquées comme les formes autorisées, les autres sont implicitement autorisées parce que C90 autorisé "int implicite" pour le type de retour et les paramètres de fonction. Aucune autre forme est autorisée.
-
C90 autonome de l'environnement
toute forme ou nom de main est autorisé 2 .
-
C99 environnement hébergé
formulaires autorisés 3 :
int main (void) int main (int argc, char *argv[]) /* or in some other implementation-defined manner. */
commentaires:
C99 supprimé "implicite int" donc
main()
n'est plus valable.Une étrange, ambigu phrase "ou, dans certains autres de la mise en œuvre définies de manière" a été introduit. Ceci peut être interprété comme "les paramètres à
int main()
peuvent varier" ou comme "main peut avoir n'importe quelle forme définie par la mise en œuvre".Certains compilateurs ont choisi d'interpréter la norme dans ce dernier. On ne peut sans doute pas facilement affirmer qu'elles ne sont pas strictement conformes en citant la norme en elle-même, car elle est ambiguë.
Cependant, pour permettre des formes complètement sauvages de
main()
était probablement(?) pas l'intention de cette nouvelle phrase. La logique C99 (non normative) implique que la phrase se réfère à des paramètres supplémentaires pourint main
4 .pourtant la section pour le programme d'environnement hébergé termination continue ensuite à argumenter sur le cas où main ne retourne pas int 5 . Bien que cette section ne soit pas normative quant à la façon dont main devrait être déclaré, elle implique certainement que main pourrait être déclaré d'une manière complètement définie par la mise en œuvre, même sur les systèmes hébergés.
-
C99 autonome de l'environnement
toute forme ou nom de main est autorisé 6 .
-
C11 environnement hébergé
formulaires autorisés 7 :
int main (void) int main (int argc, char *argv[]) /* or in some other implementation-defined manner. */
-
C11 autonome de l'environnement
toute forme ou nom de main est autorisé 8 .
notez que int main()
n'a jamais été listé comme une forme valide pour une implémentation hébergée de C dans l'une des versions ci-dessus. En C, contrairement à C++, ()
et (void)
ont des significations différentes. Le premier est la vétusté des fonctionnalité qui peut être retiré de la langue. Voir C11 langue futures directions:
6.11.6 declarateurs de fonctions
l'utilisation de déclarateurs de fonction avec des parenthèses vides (pas prototype-format paramètre Type declarators) est une fonctionnalité obsolescente.
-
C++03 environnement hébergé
formulaires autorisés 9 :
int main () int main (int argc, char *argv[])
commentaires:
notez la parenthèse vide dans la première forme. C++ et C sont différents dans ce cas, parce qu'en C++, cela signifie que la fonction ne prend aucun paramètre. Mais en C, cela signifie qu'il peut prendre n'importe quel paramètre.
-
C++03 autonome de l'environnement
le nom de la fonction appelée au démarrage est implémentation-defined. Si elle est appelée
main()
elle doit suivre les formes indiquées 10 :// implementation-defined name, or int main () int main (int argc, char *argv[])
-
C++11 hosted environnement
formulaires autorisés 11 :
int main () int main (int argc, char *argv[])
commentaires:
le texte de la norme a été modifié mais il a le même sens.
-
C++11 autonome de l'environnement
le nom de la fonction appelée au démarrage est implémentation-defined. Si elle est appelée
main()
il doit suivre les formulaires indiqués 12 :// implementation-defined name, or int main () int main (int argc, char *argv[])
références
-
ANSI X3.159-1989 2.1.2.2 environnement hébergé. "Démarrage du programme "
La fonction appelée au démarrage du programme est nommé principal. Le la mise en œuvre ne prévoit aucun prototype pour cette fonction. Il est être défini avec un type de retour de int et sans paramètres:
int main(void) { /* ... */ }
ou avec deux paramètres (appelés ici argc et argv, bien que tous les noms peuvent être utilisés, car ils sont locales à la fonction dans laquelle ils sont déclarés):
int main(int argc, char *argv[]) { /* ... */ }
-
ANSI X3.159-1989 2.1.2.1 environnement autonome:
dans un environnement autonome (dans lequel L'exécution du programme peut prendre place, sans bénéficier d'un système d'exploitation), le nom et le type de la fonction appelée au démarrage du programme sont implémentation-défini.
-
ISO 9899:1999 5.1.2.2 environnement hébergé - > 5.1.2.2.1 démarrage du programme
La fonction appelée au démarrage du programme est nommé principal. Le la mise en œuvre ne déclare aucun prototype pour de cette fonction. Il doit être défini avec un type de retour de int et sans paramètres:
int main(void) { /* ... */ }
ou avec deux paramètres (appelés ici argc et argv, bien que tous les noms peuvent être utilisés, car ils sont locales à la fonction dans laquelle ils sont déclarés):
int main(int argc, char *argv[]) { /* ... */ }
ou l'équivalent; 9)ou dans une autre application-défini manière.
-
Justification de la Norme Internationale - Langages de Programmation - C, Révision 5.10. 5.1.2.2 environnement hébergé -- > 5.1.2.2.1 démarrage du programme
Le comportement des arguments à la main, et de l'interaction de sortie, une principale et une atexit (voir §7.20.4.2) a été codifiée pour limiter certaines variétés indésirables dans la représentation de l'argv les chaînes, et dans le sens des valeurs renvoyées par la main.
la spécification de argc et argv comme arguments à main reconnaît une pratique antérieure extensive. argv[argc] doit être un pointeur nul pour fournir une vérification redondante pour la fin de la liste, également sur la base de la pratique courante.
main est la seule fonction qui peut être déclarée avec zéro ou deux arguments. (Le nombre d'arguments des autres fonctions doit correspondre exactement entre invocation et définition.) Ce cas spécial, tout simplement reconnaît la pratique répandue de laisser les arguments à main lorsque le programme n'accède pas aux chaînes d'arguments du programme. Alors que de nombreuses implémentations supportent plus de deux arguments à main, une telle pratique n'est ni bénie ni interdite par la norme; un programme qui définit main avec trois arguments n'est pas strictement conforme (voir §J. 5.1.).
-
ISO 9899:1999 5.1.2.2 environnement hébergé -- > 5.1.2.2.3 programme résiliation
si le type de retour de la fonction principale est un type compatible avec int, un retour de l'appel initial à la fonction principale est équivalent à appeler la fonction de sortie avec la valeur retournée par la fonction principale comme argument;11) atteindre le
}
qui termine la fonction principale retourne une valeur de 0. Si le type de retour n'est pas compatible avec int, l'état de terminaison retourné à l'environnement hôte n'est pas spécifié. -
ISO 9899:1999 5.1.2.1 environnement autostable
dans un environnement autonome (dans lequel L'exécution du programme C peut avoir lieu sans aucun avantage d'un système d'exploitation), le nom et le type de la fonction appelée au démarrage du programme sont définis par la mise en œuvre.
-
ISO 9899:2011 5.1.2.2 environnement hébergé - > 5.1.2.2.1 démarrage du programme
la présente section est identique à la section C99 susmentionnée.
-
ISO 9899:1999 5.1.2.1 environnement autostable
la présente section est identique à la section C99 susmentionnée.
-
ISO 14882: 2003 3.6.1 fonction principale
une implémentation ne doit pas prédéfini r la fonction principale. Ce la fonction ne doit pas être surchargé. Il doit avoir un type de retour de type int, mais sinon son type est implémentation-défini. Toutes les implémentations doivent permettre les deux définitions suivantes de main:
int main() { /* ... */ }
et
int main(int argc, char* argv[]) { /* ... */ }
-
ISO 14882: 2003 3.6.1 fonction principale
il est mis en œuvre-défini si une programme dans un environnement autonome est nécessaire pour définir une fonction principale.
-
ISO 14882: 2011 3.6.1 fonction principale
une implémentation ne doit pas prédéfini r la fonction principale. Cette fonction ne doit pas être surchargé. Il doit avoir un type de retour de type int, mais sinon son type est implémentation-défini. Toutes les implémentations doivent autoriser les deux
- un fonction de () retour int et
- une fonction de (int, pointeur à pointeur à char) retour int
comme type de main (8.3.5).
-
ISO 14882: 2011 3.6.1 fonction principale
cette section est identique à la C++03 citée ci-dessus.
Return 0 en cas de succès et non nulle pour l'erreur. C'est la norme utilisée par UNIX et DOS scripting pour découvrir ce qui s'est passé avec votre programme.
gardez à l'esprit que,même si vous retournez un int, certains OS (Windows) tronquent la valeur retournée à un seul octet (0-255).
main()
en C89 et K&R C non précisé types de retour par défaut sur "int".
return 1? return 0?
-
si vous n'écrivez pas de déclaration dans
int main()
, la fermeture{
retournera 0 par défaut. -
return 0
oureturn 1
sera reçu par le processus parent. Dans un shell il va dans une variable shell, et si vous exécutez votre programme former un shell et non en utilisant cette variable alors vous n'avez pas à vous soucier de la valeur de retour demain()
.
Voir Comment puis-je obtenir ce que ma fonction principale est de retour? .
$ ./a.out
$ echo $?
de Cette façon, vous pouvez voir que c'est la variable $?
qui reçoit l'octet le moins significatif de la valeur de retour de main()
.
Dans Unix et DOS de script, return 0
sur la réussite et l' non-zéro pour l'erreur sont généralement retournés. C'est le standard utilisé par Unix et DOS scripting pour découvrir ce qui s'est passé avec votre programme et contrôler l'ensemble du flux.
la valeur de retour peut être utilisée par le système d'exploitation pour vérifier comment le programme a été fermé.
valeur de retour 0 signifie généralement OK dans la plupart des systèmes d'exploitation (ceux auxquels je pense de toute façon).
il peut également être vérifié lorsque vous appelez un processus vous-même, et de voir si le programme a quitté et terminé correctement.
Il est PAS juste une programmation à la convention.
La valeur de retour de main()
montre comment le programme est sorti. Si la valeur de retour est zero
cela signifie que l'exécution a été réussie alors que toute valeur non nulle représentera que quelque chose s'est mal passé dans l'exécution.
j'avais l'impression que standard spécifie que main n'a pas besoin d'une valeur de retour car un retour réussi était basé sur OS (zéro dans l'un pouvait être un succès ou un échec dans l'autre), donc l'absence de retour était une indication pour le compilateur d'insérer le retour réussi lui-même.
Cependant j'ai l'habitude de retourner la valeur 0.
Returning 0 devrait dire au programmeur que le programme a terminé avec succès le travail.
ce qu'il faut retourner dépend de ce que vous voulez faire avec l'exécutable. Par exemple, si vous utilisez votre programme avec un shell en ligne de commande, vous devez retourner 0 pour un succès et un non zéro pour un échec. Alors vous seriez en mesure d'utiliser le programme dans les coquilles avec un traitement conditionnel selon le résultat de votre code. Aussi, vous pouvez assigner n'importe quelle valeur non nulle selon votre interprétation, par exemple pour les erreurs critiques différents points de sortie de programme pourraient terminer un programme avec différentes valeurs de sortie , et qui est disponible pour le shell appelant qui peut décider quoi faire en inspectant la valeur retournée.
Si le code n'est pas destiné à être utilisé avec des shells et que la valeur retournée ne dérange personne, alors il peut être omis. J'utilise personnellement la signature int main (void) { .. return 0; .. }
si vous avez vraiment des problèmes liés à l'efficacité de retourner un entier d'un processus, vous devriez probablement éviter d'appeler ce processus tellement de fois que cette valeur de retour devient un problème.
si vous faites cela (appelez un processus tellement de fois), vous devriez trouver un moyen de mettre votre logique directement à l'intérieur de l'appelant, ou dans un fichier DLL, sans affecter un processus spécifique pour chaque appel; les allocations de processus multiples vous apportent le problème d'efficacité pertinent dans ce cas.
en détail, si vous voulez seulement savoir si retourner 0 est plus ou moins efficace que retourner 1, cela pourrait dépendre du compilateur dans certains cas, mais de façon générique, en supposant qu'ils sont lus à partir de la même source (locale, de champ, constante, intégrée dans le code, résultat de la fonction, etc.) il exige exactement le même nombre de cycles d'horloge.
Quelle est la façon correcte (la plus efficace) de définir la fonction main() en C et C++ - int main() ou void main() - et pourquoi?
ces mots "(le plus efficace) " ne changent pas la question. Sauf si vous êtes dans un environnement autonome, il y a une façon universellement correcte de déclarer main()
, et c'est comme retourner int.
Quoi
main()
de retour dans le C et le C++?
ce n'est pas ce que devrait main()
retour, c'est ce que fait main()
retour. main()
est, bien sûr, une fonction que quelqu'un appelle. Vous n'avez aucun contrôle sur le code qui appelle main()
. Par conséquent, vous devez déclarer main()
avec une signature type correcte pour correspondre à son appelant. Simplement, vous n'avez pas le choix en la matière. Vous n'avez pas à vous demander ce qui est plus ou moins efficace, ou ce qui est mieux ou pire style, ou quelque chose comme ça, parce que la réponse est déjà parfaitement bien définie, pour vous, par les normes C et c+. Il suffit de suivre.
Si int main() alors retourne 1 ou 0?
0 pour le succès, non zéro pour l'échec. Encore une fois, pas quelque chose que vous devez (ou) de sélection: il est défini par l'interface, vous êtes censé être conforme.
en C++ la fonction principale doit être déclarée comme int main() et non pas void main() car le compilateur lance alors une erreur dans le cas de void main. La fonction principale peut prendre n'importe quel nombre d'arguments comme int main(int k,int l,int arr[]) ou int main(void).
#include <iostream>
using namespace std;
int main(void) {
// your code goes here
cout<<"a";
return 0;
}
sortie:
Success #stdin #stdout 0s 4416KB
a
en venant à la partie de retour, il ne doit retourner que 0 sinon le compilateur envoie une erreur. par exemple, si vous revenez 1,vous obtenez le résultat souhaité mais il jette aussi une erreur d'exécution.
exemple
#include <iostream>
using namespace std;
int main(int k,float m,char g, int arr[]) {
// your code goes here
k=0;
cout<<k;
g='a';
cout<<g;
cout<<"a";
return 1;
}
sortie:
Runtime error #stdin #stdout 0s 4448KB
0aa
Voici une petite démonstration de l'utilisation de codes de retour...
Lorsqu'on utilise les différents outils que le terminal Linux fournit, on peut utiliser le code de retour par exemple pour le traitement des erreurs après que le processus a été terminé. Imaginez que le fichier de texte suivant myfile est présent:
ceci est un exemple pour vérifier comment fonctionne grep.
lorsque vous exécutez la commande grep a processus est créé. Une fois qu'il est passé (et ne s'est pas cassé) il renvoie un code entre 0 et 255. Par exemple:
$ grep order myfile
Si vous n'
$ echo $?
$ 0
vous obtiendrez un 0. Pourquoi? Parce que grep a trouvé une correspondance et retourné un code de sortie 0, qui est la valeur habituelle pour quitter avec un succès. Vérifions à nouveau mais avec quelque chose qui n'est pas dans notre fichier texte et donc aucune correspondance ne sera trouvée:
$ grep foo myfile
$ echo $?
$ 1
Depuis grep pas correspondre aux jeton "foo" avec le contenu de notre fichier le code de retour est 1 (c'est le cas d'habitude lorsqu'une défaillance se produit, mais comme indiqué ci-dessus, vous avez beaucoup de valeurs à choisir).
maintenant le script bash suivant (simplement le taper dans un terminal Linux) bien que très basique devrait donner une idée de la gestion des erreurs:
$ grep foo myfile
$ CHECK=$?
$ [ $CHECK -eq 0] && echo 'Match found'
$ [ $CHECK -ne 0] && echo 'No match was found'
$ No match was found
après la deuxième ligne rien n'est imprimé au terminal depuis " foo" fait grep return 1 et nous vérifions si le code de retour de grep était égal à 0. Le second énoncé conditionnel fait écho à son message dans la dernière ligne puisqu'il est vrai en raison de CHECK == 1.
comme vous pouvez voir si vous appelez ceci et ce processus, il est parfois essentiel de voir ce qu'il a retourné (par la valeur de retour de main()).
Omettre return 0
Lorsqu'un programme C ou c++ atteint la fin de main
, le compilateur générera automatiquement du code pour retourner 0, Il n'est donc pas nécessaire de mettre return 0;
explicitement à la fin de main
.
Note: quand je fais cette suggestion, elle est presque invariablement suivie d'une de deux sortes de commentaires: "Je ne savais pas cela."ou "C'est un mauvais conseil!"Ma raison d'être est que c'est sûr et utile pour se fier au comportement du compilateur explicitement pris en charge par la norme. Pour C, depuis C99; voir ISO / IEC 9899: 1999 section 5.1.2.2.3:
[...] un retour de l'appel initial à la fonction
main
équivaut à appeler la fonctionexit
avec la valeur renvoyée par la fonctionmain
comme argument; atteindre la fonction}
qui termine la fonctionmain
renvoie une valeur de 0.
pour C++, depuis la première norme en 1998; voir ISO / IEC 14882: 1998 section 3.6.1:
si le contrôle atteint la fin de main sans rencontrer de déclaration de retour, l'effet est celui d'exécuter le retour 0;
toutes les versions des deux standards depuis lors (C99 et C++98) ont maintenu la même idée. Nous nous appuyons sur les fonctions de membre générées automatiquement en C++, et peu de gens écrivent explicitement return;
déclarations à la fin d'une fonction void
. Les raisons contre l'omission semblent se résumer à "il semble bizarre " . Si, comme moi, vous êtes curieux de connaître la raison d'être de la modification de la norme C , lisez la question . Il convient également de noter qu'au début des années 1990, cette pratique était considérée comme "négligente" parce qu'elle n'était pas définie (bien que largement appuyée) à l'époque.
donc je recommande de l'omettre; d'autres sont en désaccord (souvent avec véhémence!) Dans tous les cas, si vous rencontrez du code qui l'omet, vous saurez qu'il est explicitement pris en charge par la norme et vous saurez ce qu'il signifie.