2017-09-28 4 views
1

En C ce code fonctionne, ici je n'ai pas utilisé return en appelant récursivement la fonction. Il donne une sortie correcteoù utiliser return en récursion

int gcd(int a, int b) 
{ 
    if(b == 0) 
     return a; 
    gcd(b, a % b); 
} 

Mais, si je vous écris même code en python ce code renvoie Aucun (je pense que la valeur doit être renvoyée de l'instruction de retour à l'intérieur si la condition)

def gcd(a, b): 
    if b == 0: 
     return a 
    gcd(b, a % b) 

Pour rendre ce code travail, je dois ajouter retour

def gcd(a, b): 
    if b == 0: 
     return a 
    return gcd(b, a % b) 

mais pourquoi? Quelle est la différence entre l'exécution de code en C et Python sous le capot? le code en C fonctionne aussi si j'ajoute un retour supplémentaire en appelant récursivement, Pourquoi ne renvoie-t-il pas une erreur?

+3

En C chaque chemin d'exécution d'une fonction non-vide doit retourner une valeur. –

+1

Règle principale en programmation: le simple fait qu'un programme produise des résultats corrects chaque fois que vous l'avez exécuté jusqu'à présent ne signifie pas que le programme est correct. Vous avez eu de la chance dans le premier cas. Une seule valeur 'int' est typiquement retournée dans l'accumulateur primaire (' ax' dans ce cas si c'est x86) et votre 'return a' qui conclut que toute la récursivité passe un résultat dans' ax' qui revient à chaque appel de retour, inchangé (puisque votre appel récursif 'gcd' est la dernière chose que vous faites). Techniquement, vous devriez avoir 'return gcd (b, a% b)' pour que ce soit un comportement bien défini. – lurker

+0

[Notions de base sur la récursivité en Python] (https://stackoverflow.com/q/30214531/2823755), SO Q & A. – wwii

Répondre

7

Pourquoi? Faux suppositions. Incidemment, ce n'est pas une question à propos de Python, mais à propos de C. Le code C est invalide. Il a undefined behaviour parce que utilisez la valeur renvoyée d'un appel de fonction où le chemin de contrôle n'a pas utilisé l'instruction return pour en renvoyer un. Votre compilateur aurait probablement averti à ce sujet si vous compilez avec les options/paramètres corrects. C'est à dire. Ce n'est pas comment vous compilez des programmes C:

% gcc -c 123.c 

, vous activez lieu tous les avertissements, en faire des erreurs. Par exemple, dans GCC -Wall, -Wextra, -Werror et -pedantic

% gcc -c 123.c -Wall -Wextra -Werror -pedantic 
123.c: In function ‘gcd’: 
123.c:6:1: error: control reaches end of non-void function [-Werror=return-type] 
} 
^ 
cc1: all warnings being treated as errors 

Malheureusement, il y a toutes sortes de mauvais codes autour, ce qui signifie que les compilateurs C sont plus permissives par défaut que vraiment nécessaire. Un autre problème est que l'omission d'une instruction return en C n'est même pas fausse - il suffit d'utiliser la valeur de retour poubelle.

Python n'a pas de comportement indéfini de type C, donc lorsque vous omettez l'instruction return, la fonction renvoie None implicitement, et vous n'obtenez pas de déchets aléatoires qui donnent l'impression que votre code rompu a fonctionné.


Une définition de fonction plus correcte serait

int gcd(int a, int b) 
{ 
    if(b == 0) 
     return a; 
    return gcd(b, a % b); 
} 

Cependant peut-être ces arguments devraient être unsigned int de sorte que vous ne recevez pas l'idée que ce serait toujours correctement pour les nombres négatifs.

+0

mais si la fonction de valeur va 'retourner' est par 'retourner une' déclaration pourquoi avons-nous besoin de fournir un retour avant appel récursif? –

+1

@SHASHANKSHEKHAR parce que cela donne la valeur de retour seulement pour la couche * la plus interne * de l'oignon ... Incidemment ici ce sont des tortues ... 'a' tout en bas, mais les couches les plus externes n'ont pas besoin de retourner * celle *. –

2

Le code dans C a un comportement indéfini, il n'y a pas d'instruction return sur le second chemin de code (appel récursif). Vous avez de la chance que la valeur de retour soit toujours conservée dans le même registre et non écrasée, mais elle n'est pas garantie et vous risquez de recevoir du courrier indésirable.

python traite explicitement manquant chemins de retour comme return None