web-dev-qa-db-fra.com

Quelle est la déclaration appropriée de main?

Quelle est la signature correcte de la fonction main en C++? Quel est le type de retour correct et que signifie renvoyer une valeur de main? Quels sont les types de paramètres autorisés et quelle est leur signification?

Est-ce spécifique au système? Ces règles ont-elles changé au fil du temps? Que se passe-t-il si je les viole?

143
fredoverflow

La fonction main doit être déclarée en tant que fonction non membre de l'espace de noms global. Cela signifie qu'il ne peut s'agir d'une fonction membre statique ou non statique d'une classe, ni être placée dans un espace de noms (même l'espace de noms non nommé).

Le nom main n'est pas réservé en C++, sauf en tant que fonction dans l'espace de noms global. Vous êtes libre de déclarer d'autres entités nommées main, notamment des classes, des variables, des énumérations, des fonctions membres et des fonctions non membres ne figurant pas dans l'espace de noms global.

Vous pouvez déclarer une fonction nommée main en tant que fonction membre ou dans un espace de noms, mais une telle fonction ne serait pas la fonction main qui désigne l'endroit où le programme démarre.

La fonction main ne peut pas être déclarée comme static ou inline. Il ne peut pas non plus être surchargé. il ne peut y avoir qu'une seule fonction nommée main dans l'espace de noms global.

La fonction main ne peut pas être utilisée dans votre programme: vous n'êtes pas autorisé à appeler la fonction main à partir de n'importe où dans votre code, ni à prendre son adresse.

Le type de retour de main doit être int. Aucun autre type de retour n'est autorisé (cette règle est en gras car il est très courant de voir des programmes incorrects déclarant main avec un type de retour de void; il s'agit probablement de la règle la plus fréquemment enfreinte la fonction main).

Il y a deux déclarations de main qui doivent être autorisées:

int main()               // (1)
int main(int, char*[])   // (2)

Dans (1), il n'y a pas de paramètre.

Dans (2), il y a deux paramètres et ils sont conventionnellement nommés argc et argv, respectivement. argv est un pointeur sur un tableau de chaînes C représentant les arguments du programme. argc est le nombre d'arguments dans le tableau argv.

Généralement, argv[0] Contient le nom du programme, mais ce n'est pas toujours le cas. argv[argc] Est un pointeur nul.

Notez qu’un argument de type tableau (comme char*[]) N’est en réalité qu’un argument de type pointeur dissimulé, les deux suivants sont des méthodes d’écriture valables (2) et qu’ils signifient exactement la même chose:

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

Certaines implémentations peuvent autoriser d'autres types et nombres de paramètres; vous devrez vérifier la documentation de votre implémentation pour voir ce qu’elle supporte.

main() devrait renvoyer zéro pour indiquer un succès et non nul pour indiquer un échec. Vous n'êtes pas obligé d'écrire explicitement une instruction return dans main(): si vous laissez main() retourner sans une instruction explicite return, c'est la même chose que si vous aviez écrit return 0;. Les deux fonctions main() suivantes ont le même comportement:

int main() { }
int main() { return 0; }

Il existe deux macros, EXIT_SUCCESS Et EXIT_FAILURE, Définies dans <cstdlib>, Qui peuvent également être renvoyées à partir de main() pour indiquer respectivement le succès et l'échec.

La valeur renvoyée par main() est transmise à la fonction exit(), qui termine le programme.

Notez que tout cela ne s'applique que lors de la compilation pour un environnement hébergé (de manière informelle, un environnement dans lequel vous avez une bibliothèque standard complète et un système d'exploitation exécutant votre programme). Il est également possible de compiler un programme C++ pour un environnement indépendant (par exemple, certains types de systèmes intégrés), auquel cas le démarrage et la terminaison sont entièrement définis par la mise en œuvre et une fonction main() peut même ne pas être requise. . Si vous écrivez C++ pour un système d'exploitation moderne, vous compilez pour un environnement hébergé.

184
James McNellis

D'après la documentation standard, 3.6.1.2 Fonction principale ,

Le type de retour doit être de type int, mais sinon, son type est défini par l'implémentation. Toutes les implémentations doivent autoriser les deux définitions suivantes de principal:

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

Dans cette dernière forme, argc doit être le nombre d'arguments transmis 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] à argv [argc-1] en tant que pointeurs sur les caractères initiaux des chaînes multi-octets à terminaison nulle .....

J'espère que ça t'as aidé..

15
liaK

La formulation exacte de la dernière norme publiée (C++ 14) est la suivante:

Une mise en œuvre doit permettre à la fois

  • une fonction de () retournant int et

  • une fonction de (int, pointeur vers pointeur vers char) renvoyant int

comme type de main.

Cela indique clairement que les variantes orthographiques sont autorisées tant que le type de main est le type int() ou int(int, char**). Les éléments suivants sont également autorisés:

  • int main(void)
  • auto main() -> int
  • int main ( )
  • signed int main()
  • typedef char **a; typedef int b, e; e main(b d, a c)
4
M.M

Les deux valeurs valides sont int main() et int main(int, char*[]). Toute autre chose peut ou non être compilée. Si main ne renvoie pas explicitement de valeur, est renvoyé implicitement.

3
stonemetal

Détails sur les valeurs de retour et leur signification

Par 3.6.1 ([basic.start.main]):

Une instruction return dans main a pour effet de laisser la fonction main (détruire tout objet avec 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 de main sans rencontrer d'instruction return, l'effet est celui de l'exécution

return 0;

Le comportement de std::exit est détaillé dans la section 18.5 ([support.start.term]) et décrit le code de statut:

Enfin, le contrôle est renvoyé à l'environnement hôte. Si le statut est zéro ou EXIT_SUCCESS, une forme définie par l'implémentation de la condition d'état avec succès est renvoyée. Si le statut est EXIT_FAILURE, une forme définie par l'implémentation de la terminaison d'état sans succès est renvoyée. Sinon, le statut renvoyé est défini par l'implémentation.

2
Ben Voigt