Standard C - Environnement hébergé
Pour un environnement hébergé (c'est le 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 nommée main
. L'implémentation ne déclare aucun prototype pour cette fonction. Il doit être défini avec un type de retour int
et sans paramètres:
int main(void) { /* ... */ }
ou avec deux paramètres (appelés ici argc
etargv
, 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 la mise en œuvre.
S'ils sont déclarés, les paramètres de la fonction principale doivent respecter les 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 tableau argv[0]
via
argv[argc-1]
inclus doivent contenir des pointeurs vers des 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 des informations déterminées avant le démarrage du programme depuis un autre endroit de 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 garantir 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]
travers argv[argc-1]
représentent les paramètres du programme.
- Les paramètres
argc
et argv
les chaînes pointés par le argv
tableau 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 de 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 main
fonction est compatible avec un type int
, un retour de l'appel initial à la main
fonction équivaut à appeler la exit
fonction avec la valeur renvoyée par la main
fonction comme argument; 11) atteindre la }
fin de la
main
fonction renvoie une valeur de 0. Si le type de retour n'est pas compatible avec int
, l'état de terminaison renvoyé à l'environnement hôte n'est pas spécifié.
11) Conformément au 6.2.4, les durées de vie des objets avec durée de stockage automatique déclarée en main
seront terminées dans le premier cas, même si elles ne le seraient pas dans le second.
Notez que 0
c'est obligatoire 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, ainsi que 1. Voir aussi Codes de sortie supérieurs à 255 - possible? .
Dans C89 (et donc dans Microsoft C), il n'y a aucune déclaration sur ce qui se passe si la main()
fonction retourne mais ne spécifie pas de valeur de retour; il conduit donc à un comportement indéfini.
7.22.4.4 La exit
fonction
¶5 Enfin, le contrôle est retourné à 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 réussie du statut est renvoyée. Si la valeur de status
est EXIT_FAILURE
, une forme définie par l'implémentation de la terminaison d'échec d' état 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 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 par le argv[0]
biais argv[argc-1]
de pointeurs vers les caractères initiaux des chaînes multioctets à terminaison nulle (NTMBS) (17.5.2.1.4.2) et argv[0]
doivent être le pointeur sur 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 tout autre paramètre (facultatif) après argv
. —Fin note]
¶3 La fonction main
ne doit pas être utilisée dans un programme. La liaison (3.5) de main
est définie par l'implémentation. [...]
¶5 Une instruction return dans main a pour effet de quitter la fonction main (détruire tous les objets 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 de déclaration de retour, l'effet est celui de l'exécution
return 0;
Le standard C ++ dit explicitement "Il [la fonction principale] doit avoir un type de retour de type int
, mais sinon son type est défini par l'implémentation", et requiert les deux mêmes signatures que le standard C pour être pris en charge en option. Ainsi, un 'void main ()' n'est directement pas autorisé par la norme C ++, bien qu'il ne puisse rien faire pour arrêter une implémentation non standard autorisant des alternatives. Notez que C ++ interdit à l'utilisateur d'appeler main
(mais pas la norme C).
Il y a un paragraphe du §18.5 Début et fin dans la norme C ++ 11 qui est identique au paragraphe du §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 cela EXIT_SUCCESS
et qui EXIT_FAILURE
est définie 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 vers des chaînes terminée par un caractère nul, chacune étant 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;
'. Cette variable globale est unique parmi celles de POSIX en ce qu'elle n'a pas d'en-tête qui la déclare.
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 à terminaison nulle char
, chacun pointant vers une chaîne qui fournit 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 de main est
int main();
ou, éventuellement,
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
que vous retournez null, 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é en tant que void
, vous devez utiliser la exit
fonction.
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 se void main()
ferme - et le site Web de MS est également silencieux.
Fait intéressant, MS ne prescrit pas la version à deux arguments main()
requise par les normes C et C ++. Il ne prescrit qu'une forme à trois arguments où se trouve le troisième argument char **envp
, un pointeur vers une liste de variables d'environnement.
La page Microsoft répertorie également quelques autres alternatives - wmain()
qui prennent des chaînes de caractères larges, et quelques autres.
La version Microsoft Visual Studio 2005 de cette page ne figure pas void main()
comme alternative. Les versions à partir de Microsoft Visual Studio 2008 le font.
Norme C - Environnement autonome
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é), 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: 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 avec 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 d'une telle initialisation ne sont par ailleurs pas 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 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 l'implémentation. Toutes les installations de bibliothèque disponibles pour un programme indépendant, autres que l'ensemble minimal requis par l'article 4, sont définies par l'implémentation.
L'effet de l'arrêt du programme dans un environnement autonome est défini par l'implémentation.
Le renvoi à l'article 4 Conformité se réfère à ceci:
¶5 Un programme strictement conforme doit utiliser uniquement les caractéristiques du langage et de la bibliothèque spécifiés dans la présente Norme internationale. 3) Il ne doit pas produire de sortie dépendante d'un comportement non spécifié, non défini ou défini par l'implémentation, et ne doit pas dépasser une 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 mise en œuvre conforme autoportant accepte tout programme conforme strictement dans lequel l'utilisation des fonctionnalités spécifiées dans la clause bibliothèque (article 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 des fonctions de bibliothèque supplémentaires), à condition qu'elles ne modifient pas le comportement d'un programme strictement conforme. 4)
¶7 Un programme conforme est celui qui est acceptable pour une implémentation conforme. 5)
3) Un programme strictement conforme peut utiliser des fonctionnalités 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 identifiant autre que ceux explicitement réservés dans la présente Norme internationale.
5) Les programmes strictement conformes sont destinés à être portatifs au maximum parmi les implémentations conformes. Les programmes conformes peuvent dépendre de fonctionnalités non portables d'une implémentation conforme.
Il est à noter que le seul en-tête requis d'un environnement autonome qui définit réellement toutes les fonctions est <stdarg.h>
(et même celles-ci peuvent être - et sont souvent - simplement des macros).
Standard C ++ - Environnement autonome
Tout comme la norme C reconnaît à la fois l'environnement hébergé et autonome, la norme C ++ aussi. (Citations de l'ISO / CEI 14882: 2011.)
1.4 Conformité de l'implémentation [intro.compliance]
¶7 Deux types d'implémentations 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 l'avantage 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 prenant en charge les langues (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 d'un programme bien formé. Des implémentations 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 implémentation doit comprendre une documentation qui identifie toutes les constructions à prise en charge conditionnelle qu'elle ne prend pas en charge et définit toutes les caractéristiques spécifiques aux paramètres régionaux. 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émentations 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 comprendre au moins les en-têtes indiqués dans le 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 répondre 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 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 ne sont qu'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 ce 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 par 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;
}