Les arguments de la signature de main en C ++ peuvent-ils avoir les qualificatifs unsigned et const? [dupliquer]
Question
Cette question a déjà une réponse ici:
- Que doit renvoyer main () en C et C ++? 17 réponses
La norme indique explicitement que main
a deux signatures valides (c'est-à-dire garanties); à savoir:
int main();
int main(int, char*[]);
Ma question est simple. Quelque chose comme ce qui suit serait-il légal?
int main(const unsigned int, const char* const* argv);
Mes tests disent "oui", mais je ne suis pas sûr de la réponse car je ne surcharge pas main
en remplaçant int
par unsigned int
ainsi que le const
-ness non-top-level de argv? Si je le suis, c'est clairement interdit.
Ces modifications sont-elles donc garanties sur un compilateur conforme aux normes?
La solution
La norme C ++ 98 stipule à la section 3.6.1, paragraphe 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 autoriser les définitions suivantes demain
:int main ()
etint main (int argc, char * argv [])
La norme ne stipule donc pas que le paramètre acceptant env main
est acceptable, mais qu'il est autorisé.
Comme on y fait souvent référence, voici le paragraphe précédent qui exempte les environnements autonomes de tout, sauf de documenter leur comportement:
Un programme doit contenir une fonction globale appelée main, qui est le début désigné du programme. Il est mise en œuvre définie si un programme dans un environnement autonome est nécessaire pour définir un principal une fonction. [Remarque: dans un environnement autonome, le démarrage et la terminaison est définie par l'implémentation; Commencez contient l'exécution de constructeurs pour les objets de la portée de l'espace de noms avec une durée de stockage statique; Résiliation contient l'exécution des destructeurs pour les objets avec une durée de stockage statique. ]
Autres conseils
Vous devez utiliser l'une des signatures conformes à la norme pour être conforme à la norme.
Je comprends parfaitement pourquoi vous voulez le faire à votre façon. Le meilleur moyen est d'écrire votre propre fonction myMain () ou le nom de votre choix avec la signature de votre choix et de l'appeler depuis main (), y compris les conversions requises.
Les pointeurs argv
ne doivent pas être const char * const
car le programme est autorisé à modifier les tampons.
Autant que je sache, à la lecture de la norme, vous n’êtes pas conforme aux normes. Mais je ne peux pas imaginer un compilateur qui ne vous laisserait pas faire cela. Au fur et à mesure, le compilateur aurait besoin de plus de travail pour interdire spécifiquement une situation extrêmement inoffensive et très obscure.
Cela risque de ne pas fonctionner si le compilateur utilise le nom mangling pour main
. C'est une fonction C ++ après tout. Par conséquent, l'éditeur de liens recherchera deux "mutilations" particulières. Votre définition aurait un autre nom mutilé.
Notez que main
est spécial (ne surcharge pas, ne peut pas être appelé) et peut ne pas nécessiter de changement de nom.
Vous êtes peut-être illégal par rapport au standard, mais la plupart des runtimes ne s’y intéressent pas vraiment. Ils pousseront simplement un entier pour argc
et un pointeur pour argv
, appelez votre main
et espérons que vous les analyserez correctement. Dans votre domaine, vous avez donc la garantie de travailler " est discutable car le chargeur ne se soucie vraiment pas de ce que vous avez déclaré comme arguments.
S'il se construit, main
sera appelé. Comment vous analysez les arguments est à vous. Je tiens à préciser que cette question est très spécifique à la plate-forme, comme presque toute la question.
Cela dit, pourquoi?
ISO / CEI 9899: TC3
Section 5.1.2.2.1 Démarrage du programme
La fonction appelée au démarrage du programme s'appelle main. L'implémentation déclare non prototype pour cette fonction. Il doit être défini avec un type de retour int et sans valeur 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 la mise en oeuvre.