Peut une fonction récursive être en ligne?
inline int factorial(int n)
{
if(!n) return 1;
else return n*factorial(n-1);
}
Que je lisais cette, a constaté que le code ci-dessus conduirait à "l'infini de la compilation" si ce n'est pas manipulé par le compilateur correctement.
Comment le compilateur décider d'incorporer une fonction ou pas ?
Vous devez vous connecter pour publier un commentaire.
Tout d'abord, le
inline
sur une spécification de la fonction est juste un soupçon. Le compilateur peut (souvent) d'ignorer complètement la présence ou l'absence d'uninline
qualificatif. Cela dit, un compilateur peut inline une fonction récursive, autant qu'il peut dérouler une boucle infinie. Il suffit de placer une limite sur le niveau de "dérouler" la fonction.Un compilateur optimisant pourrait tourner ce code:
dans ce code:
Dans ce cas, nous avons essentiellement inline à la fonction 3 fois. Certains compilateurs ne effectuer cette optimisation. Je me souviens de MSVC++ d'avoir un réglage pour ajuster le niveau de l'in-lining, qui seront réalisés sur les fonctions récursives (jusqu'à 20, je crois).
En effet, si votre compilateur ne pas agir intelligemment, il peut essayer d'insérer des copies de vos
inline
d fonction de manière récursive, en créant à l'infini-grand code. Plus les compilateurs modernes reconnaît cela, cependant. Ils peuvent soit:Pour le cas 2, de nombreux compilateurs ont
#pragma
s vous pouvez définir pour spécifier la profondeur maximale à laquelle cela doit être fait. Dans gcc, vous pouvez également transmettre ce à partir de la ligne de commande avec--max-inline-insns-recursive
(voir plus d'infos ici).Autant que je sache, GCC fera appel tail élimination sur les fonctions récursives, si possible. Votre fonction n'est cependant pas la queue récursive.
Le compilateur crée un graphe d'appel; lorsqu'un cycle est détecté appelant elle-même, la fonction n'est plus inline après une certaine profondeur(n=1, 10, 100, quel que soit le compilateur est à l'écoute pour).
Certaines fonctions récursives peuvent être transformés en boucles, qui a effectivement infiniment inlines eux. Je crois que gcc peut le faire, mais je ne sais pas pour les autres compilateurs.
Voir les réponses déjà pourquoi ce ne présentent généralement pas de travail.
Comme une "note de bas de page", vous pouvez obtenir l'effet que vous recherchez (au moins pour la factorielle vous êtes en utilisant, comme un exemple) à l'aide de modèle de métaprogrammation. Coller de Wikipedia:
Le compilateur va faire un graphe d'appel pour détecter ces sortes de choses et de les prévenir. Il serait ainsi voir que la fonction s'appelle elle-même et non pas sur la ligne.
Mais surtout il est contrôlé par le mot-clé inline et des commutateurs du compilateur(Par exemple, vous pouvez faire l'auto inline petites fonctions, même sans le mot clé.) Il est important de noter que le Débogage des compilations ne doit jamais être inline comme la pile des appels ne seront pas conservées pour refléter les appels que vous avez créé dans le code.
"Comment le compilateur décider d'incorporer une fonction ou pas ?"
Qui dépend du compilateur, les options qui ont été spécifiées, le numéro de version du compilateur, peut-être la quantité de mémoire disponible, etc.
Le code source du programme a toujours obéir aux règles pour les fonctions inline. Si oui ou non la fonction est insérée, vous avez à vous préparer pour la possibilité qu'il soit incorporé (un inconnu nombre de fois).
Le Wikipedia déclaration que récursive macros sont généralement illégal semble plutôt mal informé. Le C et le C++ empêcher récursive des invocations, mais une unité de traduction n'est pas devenue illégale en ce qu'elle contient le code de macro qui ressemble comme il aurait été récursive. Dans des monteurs, des macros récursives sont généralement juridique.
Certains compilateurs (I. e. Borland C++) n'ont pas de code en ligne qui contient les instructions conditionnelles (si, cas, tout etc..) donc la fonction récursive dans votre exemple ne serait pas insérée.