IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Plusieurs return pour une fonction


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 607
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 607
    Par défaut Plusieurs return pour une fonction
    Bonjour

    J'aimerai avoir des avis sur la possibilité de mettre plusieurs return dans une fonction.

    Je trouve ça très pratique, ça allège le code, mais certains disent que ça gène pour le débogage. Donc, il faudrait ne mettre qu'un return par fonction

    Un exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    unsigned long fact(unsigned short n)
    {
     if (n<2) return 1;
     return n*fact(n-1);
    }
    Ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    unsigned long fact(unsigned short n)
    {
     unsigned long f;
     
     if (n<2) f=1;
     else f=n*fact(n-1);
     
     return f;
    }
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  2. #2
    Membre émérite
    Avatar de Elijha
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Avril 2003
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Avril 2003
    Messages : 314
    Par défaut
    Bonsoir,

    Je pense que cela dépend de la fonction. Si une fonction possèdent beaucoup de points de sortie (sur plus d'une vingtaine de lignes), cela commence à être coton à débugger.
    Maintenant, pour une fonction de quelques lignes, cela ne pose pas de problème.

    Il m'arrive de faire une boucle do { } while(0) et de mettre à jour une variable locale de sortie et de "casser" cette boucle par un break. C'est une autre façon de faire.
    J'avoue que je me laisse tenter de mettre des returns dans mes fonctions une fois qu'elles ont été validées.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    unsigned long fact(unsigned short n)
    {
        return (n<2)?1:n*fact(n-1) ;
    }

  3. #3
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Salut,

    Au niveau du debug, c'est surtout gênant en embarqué car les differents optimiseurs tentent de factoriser ces returns. Du coup, en pas à pas, le déroulement affiché et la réalité ne correspondent plus. On peut galérer un moment avant de comprendre que c'est la faute de l'optimiseur. Mais il y a des directives de compilations qui l'inhibent. Généralement on active l'optimiseur en mode release mais pas en mode debug.

    Ça peut également nuire à la lisibilité, mais je comprends que ce n'est pas le concept le plus intéressant quand on débute.

    A+

    Pfeuh

  4. #4
    Membre Expert Avatar de fregolo52
    Homme Profil pro
    Développeur C
    Inscrit en
    Août 2004
    Messages
    2 366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Août 2004
    Messages : 2 366
    Par défaut
    mais certains disent que ça gène pour le débogage
    Ah !! Je ne vois pas dans le cas de plusieurs return, mais c'est vrai quand on met une fonction dans le return.

    A mon ancien boulot, on avait 1 return par fonction (en général), c'était pour tracer à 1 seul endroit le retour de la fonction.

    Quelle est la meilleure solution ? Mettre plusieurs return ou un seul ? Avec 1 seul, il y aura obligatoirement des "goto end;" pour les grosses fonctions. Le goto provoque d'autres soucis.

    Donc, je dirais : mieux vaut mettre plusieurs return.

  5. #5
    Membre émérite
    Avatar de bpy1401
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2003
    Messages
    511
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2003
    Messages : 511
    Par défaut
    Bonjour à tous

    Dans ma société, nous avons définis des règles de codages , dont une qui stipule qu'il ne peut y avoir qu'un seul return dans une fonction.

    Lorsque l'on utilise un logiciel comme QAC ou PCLINT, le fait d'avoir plusieurs return dans une fonction génère un message d'erreur.

    L'objectif est d'éviter l'oublie d'un return. Dans le cas d'une fonction simple, cela a peu d'intérêt car on le voit facilement, dans le cas de fonctions complexe avec un grand nombre de if .. else if .. il est facile d'en oublier un.
    Page sur Developpez : http://pbriand.developpez.com

  6. #6
    Membre actif
    Avatar de fmdao
    Profil pro
    Formateur en informatique
    Inscrit en
    Novembre 2010
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Loire (Auvergne)

    Informations professionnelles :
    Activité : Formateur en informatique

    Informations forums :
    Inscription : Novembre 2010
    Messages : 90
    Par défaut
    1. En php ( en général avec les interpréteurs), il n'y a pas de vérification que tous les chemins renvoient une valeur.
    2. C'est vrai qu'il y a parfois des problèmes de lisibilités.
    3. Surtout cela va à l'encontre du concept de programmation structurée ( cela revient à faire un GOTO !).



    Avec 1 seul, il y aura obligatoirement des "goto end;" pour les grosses fonctions.
    Il ne devrait pas y avoir de "grosses fonctions" ! Faire un return ...; et faire un "goto end;" c'est la même chose !

  7. #7
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    Comme toujours, faire appel à son bon sens. Parfois une fonction est plus claire, ou plus sure, ou plus lisible, ou plus maintenable, en ayant un seul return. Parfois c'est l'inverse.

    Ce ne sont pas les règles de codage qui font le bon code, c'est le programmeur.

  8. #8
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 607
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 607
    Par défaut
    Citation Envoyé par Elijha Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    unsigned long fact(unsigned short n)
    {
        return (n<2)?1:n*fact(n-1) ;
    }
    Oui, mais là, je largue presque 100% de mes étudiants !
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Elijha Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    unsigned long fact(unsigned short n)
    {
        return (n<2)?1:n*fact(n-1) ;
    }
    Salut

    Personnellement je préfère mettre en premier le cas le plus souvent (statistiquement) exécuté
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    unsigned long fact(unsigned short n)
    {
        return (n>1)?n*fact(n-1) :1;
    }
    Sinon pour l'histoire des return, je pense que ce qui nuit à la qualité d'un code ce sont les extrémistes de tous bords. Autant on peut avoir une belle fonction facile à comprendre parce que justement les sorties impromptues sont gérées au début ce qui donne ensuite un code plus simple ; autant un autre cas sera mieux traité si le return est centralisé en final. Mais affirmer de façon péremptoire "il faut" ou "il ne faut pas" c'est faire montre de beaucoup de vanité. L'important c'est de bien "sentir" son code tout en prenant aussi en compte les autres critères éventuels comme le travail collaboratif, les demandes client, la compréhension par les outils annexes...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 607
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 607
    Par défaut
    Merci à tous !

    J'ai l'impression que la bonne réponse est une réponse à la normand. P't-être ben oui, p't-ëtre ben qu'non !

    Toutes vos remarques sont intéressantes.

    Et pour ce code ? Vous dites quoi ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    signed char est_premier(unsigned long nb)
    {
     unsigned long i;
     
     if (nb<2) return 0;
     if (nb==2) return 1;
     if (nb%2==0) return 0;
     
     for (i=3;i*i<=nb;i+=2)
     {
      if (nb%i==0) return 0;
     }
     
     return 1;
    }
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  11. #11
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Citation Envoyé par troumad Voir le message
    Et pour ce code ? Vous dites quoi ?
    J'aime bien, il est lisible. Les conditions sont énoncées comme le ferait un humain. C'est cependant ce multiple return précisément qui pose des problèmes de débogage en embarqué (comprendre "compilateur avec optimiseur poussé"). L'essentiel étant à mon sens d'en être conscient, car l'optimiseur se configure facilement.

    [edit] De plus quand on voit la complexité pour coder une version avec un seul return, on se demande vraiment si le jeu en vaut la chandelle. [/edit]

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    #include <assert.h>
    #include <stdio.h>
     
    int est_premier(unsigned long nb)
    {
        unsigned long i;
        int result;
     
        switch(nb)
        {
            case 0:
            case 1:
                result = 0;
                break;
            case 2:
                result = 1;
                break;
            default:
                result = 1;
                if(nb%2 == 0)
                {
                    result = 0;
                }
                else
                {
                    for (i=3; i*i<=nb; i+=2)
                    {
                        if (nb%i==0)
                        {
                             result = 0;
                             break;
                        }
                    }
                }
                break;
        }
        return result;
    }
     
    int main(int argc, char** argv)
    {
        assert(est_premier(0) == 0);
        assert(est_premier(1) == 0);
        assert(est_premier(2) == 1);
        assert(est_premier(3) == 1);
        assert(est_premier(4) == 0);
        assert(est_premier(10) == 0);
        assert(est_premier(11) == 1);
        assert(est_premier(13) == 1);
        assert(est_premier(17) == 1);
        assert(est_premier(941) == 1);
        assert(est_premier(942) == 0);
        return 0;
    }

    A+

    Pfeuh

  12. #12
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 607
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 607
    Par défaut
    C'est bien pour cette raison que j'avais opté pour plusieurs return !
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  13. #13
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    signed char est_premier(unsigned long nb)
    {
        unsigned long i;
     
        if (nb < 2)
            return 0;
     
        if  (nb == 2)
            return 1;
     
        if  (nb % 2 == 0)
            return 0;
     
        for (i = 3; i * i <= nb; i += 2)
        {
            if (nb % i == 0)
                return 0;
        }
     
        return 1;
    }
    Sinon un peu plus aéré c'est bien aussi, non ?

  14. #14
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    La faille dans tous ces codes n'est pas liée au nombre de bits d'un unsigned int (ou d'un unsigned long...). Après tout, si on déclare un paramètre en unsigned int, on peut exiger du programmeur qu'il mette un argument compatible avec un unsigned int.
    Par contre, si il met un argument compatible avec le type utilisé, il peut s'attendre à avoir une réponse exacte.
    Et ce n'est pas toujours le cas à cause de la condition erronnée i*i<=nb du for

    Supposons que le type utilisé soit sur 2n bits (on excluera du raisonnement les cas où on utilise comme type unsigned char ou unsigned short pour lesquels l'évaluation est faite différemment).
    Supposons qu'il existe un nombre premier P dans l'intervalle ](2^n-1)^2 , 2^(2n)-1]
    - Pour i = 2^n-1 la condition i*i<=P est satisfaite et on passe à i= 2^n+1
    - On a alors i*i = (2^n+1)^2 modulo(2^(2n)) = 2^(n+1)+1 , la condition i*i<=P est satisfaite et on passe à i= 2^n+3,
    - etc.
    i continue à croître et on peut alors s'attendre à la réponse "non premier" lorsque i arrivera (au bout d'un long moment) à P.

    Vérifiez, si vous le souhaitez, avec des unsigned de 32 bits et nb = 4294967291

    On peut modifier cette condition par (pour des unsigned int) i<max && i*i<=nbavec unsigned int const max = 1<< sizeof(nb)*CHAR_BIT/2;

Discussions similaires

  1. Plusieurs boutons pour une fonction
    Par SoGood dans le forum jQuery
    Réponses: 5
    Dernier message: 19/05/2013, 16h11
  2. [XL-2007] Plusieurs outputs pour une fonction
    Par Wini29 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 26/04/2013, 11h43
  3. Plusieurs return dans une fonction
    Par ninikkhuet dans le forum Langage
    Réponses: 4
    Dernier message: 19/05/2010, 12h45
  4. plusieurs return dans une fonction?
    Par contremaitre dans le forum C
    Réponses: 27
    Dernier message: 21/02/2008, 09h35
  5. [C#] Plusieurs LinkButton pour une seule fonction
    Par FunnyDjo dans le forum ASP.NET
    Réponses: 3
    Dernier message: 08/06/2005, 22h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo