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

  1. #1
    Membre à l'essai
    Homme Profil pro
    Invalidité
    Inscrit en
    mai 2019
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Invalidité

    Informations forums :
    Inscription : mai 2019
    Messages : 40
    Points : 13
    Points
    13

    Par défaut Nécessité du return dans fonction

    Bonjour a toutes et a tous ,
    J'ai fait ce petit programme en m'inspirant d'un exemple ou l'auteur utilisait un return ... a chaque fin de fonction crée . Je les ai viré et ca fonctionne quand meme . Je me suis dit que c'est normal puisque lorsque je fait l'appel de mes fonctions , je place le resultat dans une variable . Donc , dans quel cas , ils est nécéssaire de faire un return machin chose ?

    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
    #include <stdio.h>
    #include <stdlib.h>
    int nb_article();
    int remise(int nb);
     
    int main(){
     int nombre;
     int reduction;
     
     printf("Le prix du jean sans remise est de 30 euros\n");
     printf("10%% de remise entre 5 et 10 jeans acheté\n");
     printf("20%% de remise entre 10 et 100 jeans acheté\n");
     nombre=nb_article();
     printf("Vous avez séléctionné %d jeans\n",nombre);
     reduction=remise(nombre);
     printf("Le prix a l'unité sera de:%d Euros\n",reduction);
    return 0;
    }
     
    int nb_article(){
     int article;
     do{
        printf("Combien d'article voulez vous?\n");
        scanf("%d",&article);
       }while(article<=4);
     
    }
    int remise(int nb){
     int prix=30;
     int reduc,op;
     if(nb>=5 && nb<=10){
      op=(prix*10)/100;
      reduc=prix-op;}
     if(nb>10 && nb<=100){
      op=(prix*20)/100;
      reduc=prix-op;}
    }

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    5 989
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 5 989
    Points : 26 633
    Points
    26 633
    Billets dans le blog
    1

    Par défaut

    Ton truc compile parce que ton compilo est uuuultra souple, et encore.
    Tu dois avoir des warning, qui ne doivent pas être ignorés.
    Ou alors il ne compile pas du tout mais tu as une version précédente compilée qui se lance, et tu ignores la sortie qui t'indique ce comportement.

    Si une fonction retourne quelque chose (donc non void), il faut bien un moment indiquer ce qu'elle doit retourner...
    Sinon au mieux tu as des alertes ou erreurs.
    Au pire ça retourne n'importe quoi.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre éprouvé
    Avatar de emixam16
    Homme Profil pro
    Doctorant en sécurité
    Inscrit en
    juin 2013
    Messages
    237
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aube (Champagne Ardenne)

    Informations professionnelles :
    Activité : Doctorant en sécurité

    Informations forums :
    Inscription : juin 2013
    Messages : 237
    Points : 1 220
    Points
    1 220

    Par défaut

    Bonjour,

    Je ne suis pas sur de savoir quelle est ta question

    - Soit tu ne comprend pas comment marche un return. Et là je te conseille de reprendre un tutoriel depuis la première page.
    - Soit tu te poses la question un peu plus subtile suivante:
    Citation Envoyé par Version intéressante
    Mon code devrait ne pas marcher puisque ma fonction déclare retourner un int et il n'y a pas de return. Pourquoi mon code peut-il être exécuté?
    Je vais répondre à la version intéressante en espérant que ce soit la bonne...

    En fait, le C est un langage qui permet de faire beaucoup de choses, y compris "n'importe quoi". C'est dû à des raisons de design et surtout de performances.

    Normalement, quand tu fais un return, ton programme va mettre une valeur de retour dans un registre, et cette valeur va être lue par la fonction appelante. Si la fonction ne retourne rien, alors ce registre contiendra la valeur qu'il y avait avant. Ca peut être 0, 42 , -3558468, ou n'importe quoi. On parle d'un comportement indéfini (undefined behavior) (UB). C'est très mauvais, à partir du moment ou tu as un UB, considère que ton programme peut faire n'importe quoi, et peut même donner des résultats différents entre deux exécutions. C'est d'ailleurs confirmé par la norme C

    Citation Envoyé par Norme C11
    If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
    Bref, évite les UB, c'est un très bon moyen de perdre plein de temps à déboguer ton programme quand il deviendra complexe. Et ça n'amusera pas tes collègues.

    Edit: grillé
    Edit2: Arf, en relisant le message original, l'OP ne doit juste pas comprendre comment marchent les return... Et accessoirement les variables locales... Je laisse quand même mon message au cas ou il serve à un lecteur

  4. #4
    Membre à l'essai
    Homme Profil pro
    Invalidité
    Inscrit en
    mai 2019
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Invalidité

    Informations forums :
    Inscription : mai 2019
    Messages : 40
    Points : 13
    Points
    13

    Par défaut

    C'etait bien cette question que je me posais , a savoir : Mon code devrait ne pas marcher puisque ma fonction déclare retourner un int et il n'y a pas de return. Pourquoi mon code peut-il être exécuté?
    J'aurai aimé avoir un message d'erreur a la compilation, de cette facon j'aurai compris qu'il faut systématiquement faire un return apres mes fonctions non void . Mais malheureusement ca passe quand meme !
    Je vais suivre vos conseils et le faire sans manquements.
    Merci de votre aide

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    5 989
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 5 989
    Points : 26 633
    Points
    26 633
    Billets dans le blog
    1

    Par défaut

    Parce que les compilos C peuvent être souples.
    Plus ils sont vieux, plus ils le seront.
    Faudrait au moins indiquer lequel tu utilises.
    Il faut activer tous les warnings dans les options de compilation. -wall
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    Membre à l'essai
    Homme Profil pro
    Invalidité
    Inscrit en
    mai 2019
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Invalidité

    Informations forums :
    Inscription : mai 2019
    Messages : 40
    Points : 13
    Points
    13

    Par défaut

    Il s'agit de gcc version 7.4.0 .
    Je suis passé a la version version 8.3.0 . Et effectivement , apres avoir activé les warning , le manque de return sur mes fonctions est signalé !

  7. #7
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    ...
    Inscrit en
    juin 2009
    Messages
    4 252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : ...

    Informations forums :
    Inscription : juin 2009
    Messages : 4 252
    Points : 12 725
    Points
    12 725
    Billets dans le blog
    1

    Par défaut

    Seule la fonction main() autorise à ne pas avoir de return explicite. Et seulement depuis C99.

    Citation Envoyé par https://en.wikipedia.org/wiki/Entry_point#C_and_C.2B.2B
    In case a return value is not defined by the programmer, an implicit return 0; at the end of the main() function is inserted by the compiler; this behavior is required by the C++ standard.

  8. #8
    Membre à l'essai
    Homme Profil pro
    Invalidité
    Inscrit en
    mai 2019
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Invalidité

    Informations forums :
    Inscription : mai 2019
    Messages : 40
    Points : 13
    Points
    13

    Par défaut

    Par contre j'ai fais ca :

    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
    #include <stdio.h>
    #include <stdlib.h>
    #define MAX 20
     
    int nb_article(){
     int nb;
     do{
       printf("Nombre d'article voulu:\n");
       scanf("%d",&nb);
       }while(nb<5);
    return nb;
    }
     
     
    void taille(int t,int tab[]){
     int i;
     for(i=0;i<t;i++){
      printf("Entrez une taille:");
      scanf("%d",&tab[i]);}
    }
     
    int main(){
     int tab[MAX];
     int nombre,i;
     
     nombre=nb_article();
     taille(nombre,tab);
     
     printf("Le nombre d'article choisi est de:%d\n",nombre);
     printf("Les tailles choisis sont:\n");
     for(i=0;i<nombre;i++)
      printf("%d\n",tab[i]);
      puts("\n");
     return 0;
    }
    Pour ma fonction taille , j'ai pas fais de retour et meme avec le Wall , tout va bien . Pourquoi ca passe ?
    desolé pour mes questions pénible de débutant et merci de votre patience

  9. #9
    Membre éprouvé
    Avatar de emixam16
    Homme Profil pro
    Doctorant en sécurité
    Inscrit en
    juin 2013
    Messages
    237
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aube (Champagne Ardenne)

    Informations professionnelles :
    Activité : Doctorant en sécurité

    Informations forums :
    Inscription : juin 2013
    Messages : 237
    Points : 1 220
    Points
    1 220

    Par défaut

    Pour le coup c'est tout à fait normal.

    Ta fonction taille retourne void... C'est à dire vide, rien.

    Donc c'est normal que tu ne retourne rien et que ton compilo ne s'en plaigne pas, c'est le comportement attendu!

    Note de bas de page:
    Tu aurais pu aussi utiliser return; pour quitter explicitement ta fonction. Sinon, ton flot d'exécution va jusqu'à la dernière parenthèse fermante. Je te met un exemple de cas où le return; peut être utile.

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void f(int* arg) {
        if(!*arg) { // On vérifie que l'argument est valide
            perror("Nope.");
            return; // Littéralement: je retourne la valeur "rien du tout"
        }
        ++*arg; // On est sur qu'on est pas dans le cas d'erreur. On fait notre traitement.
    }
    Ici on aurait pu organiser le code pour se passer de l'early return, mais dans certains cas, cela peut rendre le code plus clair (par exemple en limitant le niveau d'indentation).

  10. #10
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    mai 2010
    Messages
    465
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : mai 2010
    Messages : 465
    Points : 1 655
    Points
    1 655

    Par défaut

    Bonjour,

    Citation Envoyé par emixam16 Voir le message
    Je te met un exemple de cas où le return; peut être utile.

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void f(int* arg) {
        if(!*arg) { // On vérifie que l'argument est valide
            perror("Nope.");
            return; // Littéralement: je retourne la valeur "rien du tout"
        }
        ++*arg; // On est sur qu'on est pas dans le cas d'erreur. On fait notre traitement.
    }
    Attention a cette instruction (!*arg)qui générera une Segmentation fault parce que l'on ne teste pas si le pointeur est valide, mais plutôt si la valeur pointée est présente ou pas ; sauf qu'en faisant ça, on utilise potentiellement un pointeur qui n'est pas initialisé dont le résultat de l'exécution de cette instruction est catastrophique.

    à bientôt
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  11. #11
    Membre à l'essai
    Homme Profil pro
    Invalidité
    Inscrit en
    mai 2019
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Invalidité

    Informations forums :
    Inscription : mai 2019
    Messages : 40
    Points : 13
    Points
    13

    Par défaut

    Difficile de faire abstraction de ses années d'experience en programmation lorsqu'on s'adresse a un debutant , n'est ce pas ?😉😀. Mais ta reponse profitera au plus grand nombre et c'est ce qui compte .

  12. #12
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    7 343
    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 : 7 343
    Points : 20 904
    Points
    20 904
    Billets dans le blog
    1

    Par défaut

    Bonjour
    Citation Envoyé par sambia39 Voir le message
    Attention a cette instruction (!*arg)qui générera une Segmentation fault parce que l'on ne teste pas si le pointeur est valide, mais plutôt si la valeur pointée est présente ou pas ; sauf qu'en faisant ça, on utilise potentiellement un pointeur qui n'est pas initialisé dont le résultat de l'exécution de cette instruction est catastrophique.
    Je ne suis pas d'accord. "arg" est effectivement un pointeur mais dans cet usage, le programmeur considère qu'il est valide car il provient de l'appelant. C'est un "à priori" tout à fait autorisé.

    Si par exemple je veux écrire un swap entre deux int, j'écrirai naturellement...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void swap(int *a, int *b) {
    	int t;
    	t=(*a);
    	(*a)=(*b);
    	(*b)=t;
    }
    ...sans me préoccuper de la validité de "a" et de "b" car je suppose que l'appelant fera les choses correctement. Et ça reste conforme à la philosophie du C du "le programmeur (appelant) sait ce qu'il fait (quand il appelle mon swap)".

    Tu as le droit évidemment de rajouter ta propre protection if (arg == NULL) return; si tu envisages cette possibilité dans une utilisation normale de ta fonction mais cela n'est pas une obligation ; d'autant plus que ça ne vérifie même pas la validité du pointeur (chose qui reste de toute façon impossible à vérifier) mais seulement de sa "non nullité" (ce qui n'est pas la même chose).
    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

  13. #13
    Membre à l'essai
    Homme Profil pro
    Invalidité
    Inscrit en
    mai 2019
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Invalidité

    Informations forums :
    Inscription : mai 2019
    Messages : 40
    Points : 13
    Points
    13

    Par défaut

    Merci a tous de votre aide

  14. #14
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    mai 2010
    Messages
    465
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : mai 2010
    Messages : 465
    Points : 1 655
    Points
    1 655

    Par défaut

    Citation Envoyé par Sve@r Voir le message
    Je ne suis pas d'accord. "arg" est effectivement un pointeur mais dans cet usage, le programmeur considère qu'il est valide car il provient de l'appelant. C'est un "à priori" tout à fait autorisé.

    Si par exemple je veux écrire un swap entre deux int, j'écrirai naturellement...
    ...sans me préoccuper de la validité de "a" et de "b" car je suppose que l'appelant fera les choses correctement. Et ça reste conforme à la philosophie du C du "le programmeur (appelant) sait ce qu'il fait (quand il appelle mon swap)".

    Tu as le droit évidemment de rajouter ta propre protection if (arg == NULL) return; si tu envisages cette possibilité dans une utilisation normale de ta fonction mais cela n'est pas une obligation ; d'autant plus que ça ne vérifie même pas la validité du pointeur (chose qui reste de toute façon impossible à vérifier) mais seulement de sa "non nullité" (ce qui n'est pas la même chose).
    Non, on ne peut pas considérer (ou systématiquement considérer) qu'arg est valide parce qu'il provient de l'appelant, il est clairement défini ici comme étant le paramètre de la fonction "f" et non l'argument qui est passé à la fonction "f" (même si l'argument "xinconnue" est référencé par le paramètre arg) et comme tu l'as si bien souligné avec ton exemple de swap, on peut parfaitement ne pas se soucier de la validité ou non-nullité de arg, car toutes précautions ou éventuels traitements sur l'argument "x" ont été prises avant l'appel à la fonction "f".

    Cependant, que ça soit dans une utilisation normale ou pas et que l'on effectue un test de validité des pointeurs, c'est pour s'assurer que le ou les pointeurs que l'on va manipuler ont été correctement initialisés d'une part et de l'autre que l'appellant qui fournit l'argument à la fonction n'a pas forcement pris des précautions et dans ce cas, on ne peut pas effectué un test de validité en accédant directement à l'objet pointé. Il vaut mieux comme tu le précaunises effectuer un if(NULL == arg) et ensuite accéder à la valeur pointée et donc,
    attention à l'instruction !*arg (avec le commentaire qui lui est associé) qui est potentiellement un pointeur non initialisé d'une part et de l'autre parce que l'on n'a également aucune idée ou exemple de l'argument qui lui est transmis ou ce qui justifie l'instruction en question.
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. plusieurs return dans une seule fonction?
    Par grodashe dans le forum Débuter
    Réponses: 4
    Dernier message: 01/01/2010, 17h09
  2. plusieurs return dans une fonction?
    Par contremaitre dans le forum C
    Réponses: 27
    Dernier message: 21/02/2008, 09h35
  3. valeur du return dans une "fonction"
    Par Papy214 dans le forum Windows Forms
    Réponses: 6
    Dernier message: 20/12/2007, 15h53
  4. Réponses: 4
    Dernier message: 25/09/2006, 13h53
  5. SSH "return" dans des fonctions
    Par geoffrey_k dans le forum Réseau
    Réponses: 6
    Dernier message: 08/11/2004, 16h19

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