c++ - personnes - tour de magie sans carte





What is the correct (most efficient) way to define the main() function in C and C++ — int main() or void main() — and why?

Those words "(most efficient)" don't change the question. Unless you're in a freestanding environment, there is one universally correct way to declare main() , and that's as returning int.

What should main() return in C and C++?

It's not what should main() return, it's what does main() return. main() is, of course, a function that someone else calls. You don't have any control over the code that calls main() . Therefore, you must declare main() with a type-correct signature to match its caller. You simply don't have any choice in the matter. You don't have to ask yourself what's more or less efficient, or what's better or worse style, or anything like that, because the answer is already perfectly well defined, for you, by the C and C+ standards. Just follow them.

If int main() then return 1 or return 0?

0 for success, nonzero for failure. Again, not something you need to (or get to) pick: it's defined by the interface you're supposed to be conforming to.


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 est appelée main . L'implémentation ne déclare aucun prototype pour 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 puissent être utilisés, car ils sont locaux à la fonction dans laquelle ils sont déclarés):

int main(int argc, char *argv[]) { /* ... */ }

ou équivalent; 10) ou d'une autre manière définie par l'implémentation.

Si elles sont déclarées, les paramètres de la fonction principale doivent obéir aux contraintes suivantes:

  • 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 groupe argv[0] à argv[argc-1] inclus doivent contenir des pointeurs sur les chaînes, qui reçoivent des valeurs définies par l'implémentation par l'environnement hôte avant le démarrage du programme. L'intention est de fournir au programme les informations déterminées avant le démarrage du programme à partir d'ailleurs dans l'environnement hébergé. Si l'environnement hôte n'est pas capable de fournir des chaînes avec des lettres majuscules et minuscules, l'implémentation doit s'assurer que les chaînes sont reçues en minuscules.
  • Si la valeur de argc est supérieure à zéro, la chaîne pointée par argv[0] représente le nom du programme; argv[0][0] doit être le caractère nul si le nom du programme n'est pas disponible dans l'environnement hôte. Si la valeur de argc est supérieure à un, les chaînes pointées par argv[1] à argv[argc-1] représentent les paramètres du programme.
  • Les paramètres argc et argv et les chaînes pointées par le tableau argv doivent être modifiables par le programme et conserver leurs dernières valeurs stockées entre le démarrage du programme et la fin du programme.

10) Ainsi, int peut être remplacé par un nom typedef défini comme int , ou le type d' argv peut être écrit comme char **argv , et ainsi de suite.

Fin du programme en C99 ou C11

La valeur renvoyée par main() est transmise à l'environnement d'une manière définie par l'implémentation.

5.1.2.2.3 Fin du programme

1 Si le type de retour de la fonction main est un type compatible avec int , un retour de l'appel initial à la fonction main équivaut à appeler la fonction exit avec la valeur renvoyée par la fonction main comme argument; 11) atteignant le } qui termine la fonction main renvoie une valeur de 0. Si le type de retour n'est pas compatible avec int , le statut de terminaison renvoyé à l'environnement hôte n'est pas spécifié.

11) Conformément à 6.2.4, les durées de vie des objets avec une durée de stockage automatique déclarée dans main seront terminées dans le premier cas, même s'ils ne le seraient pas dans le second cas.

Notez que 0 est mandaté comme 'succès'. Vous pouvez utiliser EXIT_FAILURE et EXIT_SUCCESS partir de <stdlib.h> si vous préférez, mais 0 est bien établi, tout comme 1. EXIT_FAILURE - EXIT_SUCCESS également des codes de sortie supérieurs à 255 - possibles? .

En C89 (et donc dans Microsoft C), il n'y a aucune déclaration sur ce qui se passe si la fonction main() renvoie mais ne spécifie pas de valeur de retour; il conduit donc à un comportement indéfini.

7.22.4.4 La fonction de exit

¶5 Enfin, le contrôle est renvoyé à l'environnement hôte. Si la valeur de status est zéro ou EXIT_SUCCESS , une forme définie par l'implémentation de la terminaison d'état est renvoyée. Si la valeur de status est EXIT_FAILURE , une forme définie par l'implémentation de l' arrêt de l'état infructueux est renvoyée. Sinon, le statut renvoyé 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 [basic.start.main]

¶1 Un programme doit contenir une fonction globale appelée main, qui est le début désigné du programme. [...]

¶2 Une implémentation ne doit pas prédéfinir la fonction principale. Cette fonction ne doit pas être surchargée. Il doit avoir un type de retour de type int, mais sinon son type est défini par l'implémentation. Toutes les implémentations doivent permettre les deux définitions suivantes de main:

int main() { /* ... */ }

et

int main(int argc, char* argv[]) { /* ... */ }

Dans la dernière forme, argc sera le nombre d'arguments passés au programme à partir de l'environnement dans lequel le programme est exécuté. Si argc est différent de zéro, ces arguments doivent être fournis dans argv[0] via argv[argc-1] comme pointeurs sur les caractères initiaux des chaînes multi-octets à terminaison nulle (NTMBS) (17.5.2.1.4.2) et argv[0] doit être le pointeur vers le caractère initial d'un NTMBS qui représente le nom utilisé pour appeler le programme ou "" . La valeur de argc doit être non négative. La valeur de argv[argc] doit être 0. [Remarque: Il est recommandé d'ajouter d'autres paramètres (facultatifs) après argv . -end note]

¶3 La fonction main ne doit pas être utilisée dans un programme. Le lien (3.5) de main est défini par l'implémentation. [...]

¶5 Une instruction return dans main a pour effet de quitter la fonction principale (en détruisant tous les objets ayant une durée de stockage automatique) et d'appeler std::exit avec la valeur de retour comme argument. Si le contrôle atteint la fin du principal sans rencontrer d'instruction return, l'effet est celui de l'exécution

return 0;

La norme C ++ dit explicitement "It [la fonction principale] doit avoir un type de retour de type int , mais sinon son type est défini par l'implémentation", et nécessite les deux mêmes signatures que la norme C pour être supportées en tant qu'options. Donc 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. Notez que C ++ interdit à l'utilisateur d'appeler main (mais pas le standard C).

Il y a un paragraphe de §18.5 Début et fin dans la norme C ++ 11 qui est identique au paragraphe du §7.22.4.4 La fonction de exit dans la norme C11 (citée ci-dessus), à part une note de bas de page (qui documente simplement EXIT_SUCCESS et EXIT_FAILURE sont définis dans <cstdlib> ).

Norme C - Extension commune

Classiquement, les systèmes Unix prennent en charge une troisième variante:

int main(int argc, char **argv, char **envp) { ... }

Le troisième argument est une liste de pointeurs terminés par des caractères NULL, dont chacun 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; '. Pendant longtemps, il n'y avait pas d'en-tête qui le déclarait, mais le standard POSIX 2008 exige maintenant qu'il soit déclaré dans <unistd.h> .

Ceci est reconnu par la norme C comme une extension commune, 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 terminés par un caractère nul, dont chacun pointe vers une chaîne fournissant des informations sur l'environnement pour cette exécution. du programme (5.1.2.2.1).

Microsoft C

Le compilateur Microsoft VS 2010 est intéressant. Le site web dit:

La syntaxe de déclaration pour principal est

 int main();

ou, en option,

int main(int argc, char *argv[], char *envp[]);

Alternativement, les fonctions main et wmain peuvent être déclarées comme retournant void (pas de valeur de retour). Si vous déclarez main ou wmain comme retournant void, vous ne pouvez pas renvoyer un code de sortie au processus parent ou au système d'exploitation à l'aide d'une instruction return. Pour renvoyer un code de sortie lorsque main ou wmain est déclaré comme void , vous devez utiliser la fonction exit .

Il n'est pas clair pour moi ce qui se passe (quel code de sortie est retourné au parent ou au système d'exploitation) lorsqu'un programme avec void main() quitte - et le site Web MS est également silencieux.

Fait intéressant, MS ne prescrit pas la version à deux arguments de main() que les normes C et C ++ exigent. Il prescrit seulement une forme à trois arguments où le troisième argument est char **envp , un pointeur vers une liste de variables d'environnement.

La page Microsoft répertorie également d'autres alternatives - wmain() qui prend des chaînes de caractères larges, et d'autres.

La version Microsoft Visual Studio 2005 de cette page ne répertorie pas void main() comme alternative. Les versions partir de Microsoft Visual Studio 2008 font.

Norme C - Environnement autoportant

Comme indiqué précédemment, 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 pas de contraintes sur son type de retour. La norme dit:

5.1.2 Environnements d'exécution

Deux environnements d'exécution sont définis: autonome et hébergé. Dans les deux cas, le démarrage du programme se produit lorsqu'une fonction C désignée est appelée par l'environnement d'exécution. Tous les objets ayant une durée de stockage statique doivent être initialisés (définis sur leurs valeurs initiales) avant le démarrage du programme. La manière et le moment de cette initialisation sont par ailleurs non spécifiés. La fin du programme renvoie le contrôle à l'environnement d'exécution.

5.1.2.1 Environnement autonome

Dans un environnement autonome (dans lequel l'exécution du programme C peut avoir lieu 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 définis par l'implémentation. Toute bibliothèque disponible pour un programme autonome, autre que l'ensemble minimal requis par la clause 4, est définie par l'implémentation.

L'effet de la terminaison du programme dans un environnement autonome est défini par l'implémentation.

La référence croisée à la clause 4 Conformité se réfère à ceci:

¶5 Un programme strictement conforme ne doit utiliser que les caractéristiques de la langue et de la bibliothèque spécifiées dans la présente Norme internationale. 3) Il ne doit pas produire de résultat dépendant d'un comportement non spécifié, indéfini ou défini par l'implémentation, et ne doit pas dépasser toute limite d'implémentation minimale.

¶6 Les deux formes d'implémentation conforme sont hébergées et autonomes . Une implémentation hébergée conforme doit accepter tout programme strictement conforme. Une implémentation autonome conforme doit accepter tout programme strictement conforme dans lequel l'utilisation des fonctionnalités spécifiées dans la clause library (clause 7) est limitée au contenu des en-têtes standard <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 des fonctions de bibliothèque supplémentaires), à condition qu'elles ne modifient pas le comportement de tout programme strictement conforme. 4)

¶7 Un programme conforme est un programme acceptable pour une implémentation 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 de prétraitement d'inclusion conditionnelle appropriée utilisant la macro associée. Par exemple:

#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */
    /* ... */
    fesetround(FE_UPWARD);
    /* ... */
#endif

4) Cela implique qu'une implémentation conforme ne réserve aucun identificateur autre que ceux explicitement réservés dans la présente Norme internationale.

5) Les programmes strictement conformes sont conçus pour être portables au maximum parmi les implémentations conformes. Les programmes conformes peuvent dépendre de caractéristiques non portables d'une implémentation conforme.

Il est à noter que le seul en-tête requis pour un environnement autonome définissant réellement des fonctions est <stdarg.h> (et même ceux-ci peuvent être - et sont souvent - juste des macros).

Standard C ++ - Environnement autoportant

Tout comme la norme C reconnaît les environnements hébergés et autonomes, la norme C ++ le permet également. (Citations de l'ISO / CEI 14882: 2011.)

1.4 Conformité de l'implémentation [intro.compliance]

¶7 Deux types d'implémentation sont définis: une implémentation hébergée et une implémentation autonome . Pour une implémentation hébergée, la présente Norme internationale définit l'ensemble des bibliothèques disponibles. Une implémentation autonome est une implémentation dans laquelle l'exécution peut avoir lieu sans bénéficier d'un système d'exploitation, et possède un ensemble de bibliothèques défini par l'implémentation qui inclut certaines bibliothèques de support de langage (17.6.1.3).

¶8 Une implémentation conforme peut avoir des extensions (y compris des fonctions de bibliothèque supplémentaires), à condition qu'elles ne modifient pas le comportement de tout programme bien formé. Des mises en œuvre sont nécessaires pour diagnostiquer les programmes qui utilisent de telles extensions mal formées conformément à la présente Norme internationale. Cela fait, cependant, ils peuvent compiler et exécuter de tels programmes.

¶9 Chaque mise en œuvre doit inclure une documentation qui identifie toutes les constructions prises en charge de manière conditionnelle et ne définit pas les caractéristiques spécifiques à la localisation. 3

3) Cette documentation définit également le comportement défini par l'implémentation; voir 1.9.

17.6.1.3 Implémentations autonomes [conformité]

Deux types d'implémentation sont définis: hébergé et autonome (1.4). Pour une implémentation hébergée, la présente Norme internationale décrit l'ensemble des en-têtes disponibles.

Une implémentation autonome possède un ensemble d'en-têtes défini par l'implémentation. Cet ensemble doit inclure au moins les en-têtes du tableau 16.

La version fournie de l'en-tête <cstdlib> doit déclarer au moins les fonctions abort , atexit , at_quick_exit , exit et quick_exit (18.5). Les autres en-têtes répertoriés dans ce tableau doivent satisfaire aux mêmes exigences que pour une implémentation hébergée.

Tableau 16 - En-têtes C ++ 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>

Qu'en est-il de l'utilisation de 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() : §6.5.3.4 ¶8 et §6.7.6.3 ¶20 . Maintenant, il est important de noter que les exemples ne sont pas «normatifs»; ils sont seulement illustratifs. S'il y a des bogues dans les exemples, ils n'affectent pas directement le texte principal de la norme. Cela dit, ils sont fortement indicatifs du comportement attendu, donc si la norme inclut int main() dans un exemple, cela 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 opérateurs sizeof et _Alignof

...

¶8 EXEMPLE 3 Dans cet exemple, la taille d'un tableau de longueur variable est calculée et renvoyé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 EXIT_SUCCESS ou EXIT_FAILURE . Ils sont définis dans stdlib.h


La réponse acceptée semble être ciblée pour C ++, donc j'ai pensé que j'ajouterais une réponse qui se rapporte à C, et cela diffère de plusieurs façons.

ISO / CEI 9899: 1989 (C90):

main() doit être déclaré comme:

int main(void)
int main(int argc, char **argv)

Ou équivalent. Par exemple, int main(int argc, char *argv[]) est équivalent au second. En outre, le type int return peut être omis car il s'agit d'un défaut.

Si une implémentation le permet, main() peut être déclaré d'autres façons, mais cela rend l'implémentation du programme définie, et n'est plus strictement conforme.

La norme définit 3 valeurs de retour strictement conformes (c'est-à-dire qui ne s'appuient pas sur le comportement défini par l'implémentation): 0 et EXIT_SUCCESS pour une terminaison réussie, et EXIT_FAILURE pour une résiliation infructueuse. Toutes les autres valeurs sont non standard et implémentées. main() doit avoir une déclaration de return explicite à la fin pour éviter un comportement indéfini.

Enfin, il n'y a rien de mal du point de vue des standards en appelant main() depuis un programme.

ISO / CEI 9899: 1999 (C99):

Pour C99, tout est le même que ci-dessus sauf:

  • Le type de retour int ne peut pas être omis.
  • Vous pouvez omettre l'instruction return de main() . Si vous le faites, et main() fini, il y a un return 0 implicite return 0 .

Notez que les normes C et C ++ définissent deux types d'implémentations: autonome et hébergé.

  • Environnement hébergé C90

    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 premiers sont explicitement déclarés comme les formes autorisées, les autres sont implicitement autorisés car C90 a permis "implicite int" pour le type de retour et les paramètres de fonction. Aucune autre forme n'est autorisée.

  • Environnement autonome C90

    Toute forme ou nom de main est autorisé 2 .

  • Environnement hébergé C99

    Formulaires autorisés 3 :

    int main (void)
    int main (int argc, char *argv[])
    /* or in some other implementation-defined manner. */
    

    Commentaires:

    C99 a supprimé "implicit int", donc main() n'est plus valide.

    Une phrase étrange, ambiguë "ou d'une autre manière définie par l'implémentation" a été introduite. Cela peut être interprété comme "les paramètres de int main() peuvent varier" ou "main peut avoir n'importe quel formulaire défini par l'implémentation".

    Certains compilateurs ont choisi d'interpréter la norme de cette manière. Sans doute, on ne peut pas facilement dire qu'ils ne se conforment pas strictement en citant la norme en soi, puisqu'elle est ambiguë.

    Cependant, permettre des formes complètement sauvages de main() n'é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 à int main 4 .

    Pourtant, la section pour la terminaison du programme de l'environnement hébergé continue alors à se disputer sur le cas où main ne renvoie pas int 5 . Bien que cette section ne soit pas normative quant à la façon dont la fonction principale doit être déclarée, elle implique clairement que la fonction principale peut être déclarée d'une manière complètement mise en œuvre, même sur les systèmes hébergés.

  • Environnement autonome C99

    Toute forme ou nom de main est autorisé 6 .

  • Environnement hébergé C11

    Formulaires autorisés 7 :

    int main (void)
    int main (int argc, char *argv[])
    /* or in some other implementation-defined manner. */
    
  • Environnement autonome C11

    Toute forme ou nom de main est autorisé 8 .

Notez que int main() n'a jamais été répertorié comme un formulaire valide pour toute 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 un élément obsolète qui peut être retiré de la langue. Voir les directions linguistiques futures du C11:

6.11.6 Les déclarateurs de fonction

L'utilisation de déclarateurs de fonction avec des parenthèses vides (et non des déclarateurs de type de paramètre au format prototype) est une fonction obsolète.

  • Environnement hébergé C ++ 03

    Formulaires autorisés 9 :

    int main ()
    int main (int argc, char *argv[])
    

    Commentaires:

    Notez la parenthèse vide dans le premier formulaire. C ++ et C sont différents dans ce cas, car 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.

  • Environnement autonome C ++ 03

    Le nom de la fonction appelée au démarrage est défini par l'implémentation. Si elle s'appelle main() elle doit suivre les formes indiquées 10 :

    // implementation-defined name, or 
    int main ()
    int main (int argc, char *argv[])
    
  • Environnement hébergé C ++ 11

    Formulaires autorisés 11 :

    int main ()
    int main (int argc, char *argv[])
    

    Commentaires:

    Le texte de la norme a été modifié mais il a la même signification.

  • Environnement autonome C ++ 11

    Le nom de la fonction appelée au démarrage est défini par l'implémentation. Si elle s'appelle main() elle doit suivre les formes indiquées 12 :

    // implementation-defined name, or 
    int main ()
    int main (int argc, char *argv[])
    

Les références

  1. 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 appelée main. L'implémentation ne déclare aucun prototype pour 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 puissent être utilisés, car ils sont locaux à la fonction dans laquelle ils sont déclarés):

    int main(int argc, char *argv[]) { /* ... */ }
    
  2. ANSI X3.159-1989 2.1.2.1 Environnement autoportant:

    Dans un environnement autonome (dans lequel l'exécution du programme C peut avoir lieu 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 définis par l'implémentation.

  3. 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 appelée main. L'implémentation ne déclare aucun prototype pour 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 puissent être utilisés, car ils sont locaux à la fonction dans laquelle ils sont déclarés):

    int main(int argc, char *argv[]) { /* ... */ }
    

    ou équivalent 9) ou d'une autre manière définie par l'implémentation.

  4. 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

    The behavior of the arguments to main, and of the interaction of exit, main and atexit (see §7.20.4.2) has been codified to curb some unwanted variety in the representation of argv strings, and in the meaning of values returned by main.

    The specification of argc and argv as arguments to main recognizes extensive prior practice. argv[argc] is required to be a null pointer to provide a redundant check for the end of the list, also on the basis of common practice.

    main is the only function that may portably be declared either with zero or two arguments. (The number of other functions' arguments must match exactly between invocation and definition.) This special case simply recognizes the widespread practice of leaving off the arguments to main when the program does not access the program argument strings. While many implementations support more than two arguments to main, such practice is neither blessed nor forbidden by the Standard; a program that defines main with three arguments is not strictly conforming (see §J.5.1.).

  5. ISO 9899:1999 5.1.2.2 Hosted environment --> 5.1.2.2.3 Program termination

    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;11) 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.

  6. ISO 9899:1999 5.1.2.1 Freestanding environment

    In a freestanding environment (in which C program execution may take place without any benefit of an operating system), the name and type of the function called at program startup are implementation-defined.

  7. ISO 9899:2011 5.1.2.2 Hosted environment -> 5.1.2.2.1 Program startup

    This section is identical to the C99 one cited above.

  8. ISO 9899:1999 5.1.2.1 Freestanding environment

    This section is identical to the C99 one cited above.

  9. ISO 14882:2003 3.6.1 Main function

    An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations shall allow both of the following definitions of main:

    int main() { /* ... */ }
    

    et

    int main(int argc, char* argv[]) { /* ... */ }
    
  10. ISO 14882:2003 3.6.1 Main function

    It is implementation-defined whether a program in a freestanding environment is required to define a main function.

  11. ISO 14882:2011 3.6.1 Main function

    An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations shall allow both

    — a function of () returning int and

    — a function of (int, pointer to pointer to char) returning int

    as the type of main (8.3.5).

  12. ISO 14882:2011 3.6.1 Main function

    This section is identical to the C++03 one cited above.


Renvoie 0 en cas de succès et non nul en cas d'erreur. C'est la norme utilisée par les scripts UNIX et DOS pour savoir ce qui s'est passé avec votre programme.


Here is a small demonstration of the usage of return codes...

When using the various tools that the Linux terminal provides one can use the return code for example for error handling after the process has been completed. Imagine that the following text file myfile is present:

This is some example in order to check how grep works.

When you execute the grep command a process is created. Once it is through (and didn't break) it returns some code between 0 and 255. For example:

$ grep order myfile

If you do

$ echo $?
$ 0

you will get a 0. Why? Because grep found a match and returned an exit code 0, which is the usual value for exiting with a success. Let's check it out again but with something that is not inside our text file and thus no match will be found:

$ grep foo myfile
$ echo $?
$ 1

Since grep failed to match the token "foo" with the content of our file the return code is 1 (this is the usual case when a failure occurs but as stated above you have plenty of values to choose from).

Now the following bash script (simply type it in a Linux terminal) although very basic should give some idea of error handling:

$ grep foo myfile
$ CHECK=$?
$ [ $CHECK -eq 0] && echo 'Match found'
$ [ $CHECK -ne 0] && echo 'No match was found'
$ No match was found

After the second line nothing is printed to the terminal since "foo" made grep return 1 and we check if the return code of grep was equal to 0. The second conditional statement echoes its message in the last line since it is true due to CHECK == 1.

As you can see if you are calling this and that process it is sometimes essential to see what it has returned (by the return value of main()).


I was under the impression that standard specifies that main doesn't need a return value as a successful return was OS based (zero in one could be either a success or a failure in another), therefore the absence of return was a cue for the compiler to insert the successful return itself.

However I usually return 0.


In C++ the main function should be declared as int main() and not void main() as the compiler then throws an error in the case of void main. The main function can take any number of arguments like int main(int k,int l,int arr[]) or 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

Coming to the return part it should return only 0 else the compiler throws an error. for example if you return 1,you will get the desired output but it also throws a runtime error.

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

Keep in mind that,even though you're returning an int, some OSes (Windows) truncate the returned value to a single byte (0-255).


The return value can be used by the operating system to check how the program was closed.

Return value 0 usually means OK in most operating systems (the ones I can think of anyway).

It also can be checked when you call a process yourself, and see if the program exited and finished properly.

It's NOT just a programming convention.


The return value of main() shows how the program exited. If the return value is zero it means that the execution was successful while any non-zero value will represent that something went bad in the execution.


What to return depends on what you want to do with the executable. For example if you are using your program with a command line shell, then you need to return 0 for a success and a non zero for failure. Then you would be able to use the program in shells with conditional processing depending on the outcome of your code. Also you can assign any nonzero value as per your interpretation, for example for critical errors different program exit points could terminate a program with different exit values , and which is available to the calling shell which can decide what to do by inspecting the value returned. If the code is not intended for use with shells and the returned value does not bother anybody then it might be omitted. I personally use the signature int main (void) { .. return 0; .. }





return-type