La fonction principale peut-elle s'appeler en C ++?
Quelqu'un peut dire quel est le problème de le code ci-dessous?
int main () {
return main();
}
Je l'ai testé, il compile correctement. C'est de la course à jamais. Plus tour derrière la scène?
source d'informationauteur skydoor
Vous devez vous connecter pour publier un commentaire.
TLDR: Appel
main
résultats dans un comportement indéfini.Il semble y avoir confusion au sujet de la terminologie utilisée dans la norme, et les implications qu'elle a pour le programmeur et le compilateur.
Tout d'abord, la norme seul détermine tout sur le langage C++. Si votre version particulière d'un compilateur permet une action particulière, qui n'a aucune incidence sur si oui ou non cette action est légale. Pour le reste du post, je fais référence à la ISO03 standard.
Donc, pour citer une fois de plus, la norme est dit au §3.6.1.3:
En outre, §3.2 définit "utilisé" comme:
Cela signifie qu'une fois que le programme commence à exécuter,
main
devrait ne jamais être entré de nouveau. Cela signifie que les programmeurs ne peut pas appelermain
cela signifie que le compilateur ne peut pas insérer un autre appel àmain
(pourquoi, qui sait), vous ne pouvez pas prendre l'adresse de principal et d'appel qui, etc. Vous ne pouvez pas même avoir le potentiel de l'appelmain
.Le seul appel à
main
devrait être par la bibliothèque run-time le programme est en cours d'exécution sur tous les autres appels appeler un comportement indéfini. (Ce qui signifie que tout peut arriver!)Maintenant sur le comportement du compilateur:
Reçu un diagnostic de la règle est définie comme (§1.4.1):
Dans notre cas, §3.6.1.3 définit reçu un diagnostic de règle. Voici ce que les compilateurs doivent le faire conformément au §1.4.2:
Donc compilateurs sont pas nécessaires pour faire respecter les règles. Tous les compilateurs ont à faire est de prendre bien formé programmes (§1.3.14) et de les transformer en un programme exécutable. Un compilateur est libre d'avertissement, erreur, etc. cependant il aime, tant qu'il n'entre pas en conflit avec la langue. Il est nécessaire pour afficher un message dans notre cas particulier, selon le deuxième alinéa.
Pour ce problème particulier, sur gcc le
-pedantic
option avertir à propos de l'illégalité de l'appelmain
dans le programme. Visual Studio pas avertir à propos de l'appel demain
mais sur n'importe quel niveau d'avertissement (supérieur à 0), il va avertir à propos de la nature récursive de la programme de.Qu'est-ce que cela signifie en termes de réponses que vous devriez vous attendre? Cela signifie qu'il est complètement dénuée de sens pour essayer de le définir avec certitude ce que l'extrait de code posté le fera. L'appel de
main
résultats dans un comportement indéfini, et en essayant de définir un comportement indéfini est évidemment une cause perdue. La seule réponse honnête, n'importe qui peut donner à "ce qui se passe quand je l'appellemain
?" est "n'importe Quoi".J'espère que cela efface les choses.
Appel
main
en C++ est illégal (§3.6.1.3):Votre compilateur est de permettre à un comportement illégal.
Il fait une boucle pour toujours parce que, eh bien,
main
appelsmain
qui appellemain
qui appellemain
et ainsi de suite.C'est comme une drogue distributeur. Assez illégal, mais compile et fonctionne même hors bon pour un certain temps...
La question est, pourquoi voudriez-vous?
principal est censé être un seul point d'entrée de votre programme. En l'appelant de nouveau essentiellement redémarrage de votre programme, mais sans une nouvelle instance du processus, aucune nouvelle pile, pas de nouveau tas, etc.
Si vous avez vraiment besoin de récursivité, appelez une autre fonction récursive.
La norme C++, dans la section 3.6.1, il dit:
Il spécifie, vous n'êtes pas censé l'appeler à partir de votre programme.
Bien sûr, si vous voulez vraiment appeler votre principale fonction récursive, et parfois il y a de bonnes raisons, vous devriez faire ce
Lorsque vous écrivez du code récursif, vous devez vous assurer que vous arrêter recursing, sinon tu viens d'écrire une boucle infinie.
Que vous avez.
Vous devriez vous attendre de ce code à aller loin pour un long temps et puis finalement collision avec un débordement de pile.
Vous avez deux questions. Le premier est l'appel principal qui, comme cela a été souligné à la fois viole la norme et le but de la norme.
Le plus gros problème est que vous avez écrit un appel récursif, sans point de fermeture. Vous question semble supposer que la version de principal appelé par la première, on vient de revenir. Cependant, la plupart des langues (en fait tout ce que je peux penser) a permis illimité de récursivité: si une fonction s'appelle elle-même alors que la version sera ainsi. La seule limite est celle de ressources système.
Si vous avez besoin d'envelopper l'appel à une condition, et seulement de continuer à appeler en cas de besoin. Dans votre exemple, l'ajout d'un mondial entier définir le nombre de niveaux que vous voulez répéter serait de travailler. Quelque chose comme ceci:
`
`
Quitter.
Tandis que votre programme n'a évidemment aucun sens, comme il fait une boucle pour toujours, ça peut paraître possible de faire quelque chose comme:
Cependant, la norme ne l'autorise pas. (Voir les autres réponses)
Bien sûr, vous pouvez mettre en œuvre que, ce faisant,