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 :

Quelques précisions. . .


Sujet :

C

  1. #21
    Membre du Club Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Points : 55
    Points
    55
    Par défaut
    Bonjour,

    Une question bien idiote...

    J'aimerais savoir si l'on peut utiliser un tableau comme valeur de retour dans une fonction.
    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
     
    #include <stdio.h>
     
    char gpp(void);
     
    int main(void) {
    	printf("%s\n", gpp());
    	return 0;
    }
     
    char gpp(void) {
    	char gpp[6];
    	gpp[0] = 'h';
    	gpp[1] = 'e';
    	gpp[2] = 'l';
    	gpp[3] = 'l';
    	gpp[4] = 'o';
    	gpp[5] = '\0';
    	return gpp;
    }
    Si je compile ce programme, j'ai une erreur me venant de Windows, c'est à dire que le programme quitte inopinément.

    C'est probablement un problème relatif à gpp() . . .
    ou peut-être ne peut on pas avoir un tableau comme valeur de retour . . .


    Que faire!?

    Merci,

    Array

  2. #22
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Array Voir le message
    Bonjour,

    Une question bien idiote...

    J'aimerais savoir si l'on peut utiliser un tableau comme valeur de retour dans une fonction.



    Si je compile ce programme, j'ai une erreur me venant de Windows, c'est à dire que le programme quitte inopinément.

    C'est probablement un problème relatif à gpp() . . .
    ou peut-être ne peut on pas avoir un tableau comme valeur de retour . . .


    Que faire!?

    Merci,

    Array
    Attention, le prototype de ta fonction n'est pas correct. Il doit être:
    Déclaré comme dans l'exemple que tu proposes (Attention, c'est la balise CODE qu'il faut utiliser et non QUOTE), la mémoire pour le tableau gpp que tu proposes est alloué dans un espace appelé la pile. Cet espace est libéré automatiquement dès qu'on sort de la fonction. Or, dans ton exemple, l'instruction return gpp retourne l'adresse du premier élément de ton tableau qui correspond dès lors à une adresse invalide, car cet espace a été libéré à la sortie de la fonction.

    Si tu désires que ta fonction retourne l'adresse d'un tableau, il faut que la mémoire pour ce dernier ait été alloué dynamiquement dans un espace mémoire qu'on appelle le tas. Cette allocation utilise la fonction malloc() déclarée dans le fichier d'en-tête standard stdlib.h. Voici un exemple:

    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>
    #include <string.h>
     
    char *gpp(void)
    {
        char *ret = NULL; /* Valeur retournée par la fonction */
     
        char const *s_hello = "Hello world";
        size_t length = strlen(s_hello) + 1;
        char *message = NULL;
     
        /* On alloue l'espace mémoire nécessaire sur le tas */
        message = malloc(length * sizeof *message);
        /* Toujours vérifier la valeur retournée par malloc() */
        if (message != NULL)
        {
            /* On copie le contenu de s_hello dans message */
            *message = 0;
            strncat(message, s_hello, length - 1);
     
            ret = message;
        }
        return ret;
    }
     
    int main(void)
    {
        char *s_chaine = gpp();
        printf("%s\n", s_chaine);
        /* Ne pas oublier de libérer la mémoire */
        free(s_chaine), s_chaine = NULL;
     
        return EXIT_SUCCESS;
    }
    Toutefois, ce n'est qu'un exemple d'utilisation de l'allocation dynamique. On est bien d'accord qu'il n'est en général pas nécessaire de recourir à ce type de stratégies pour afficher un simple 'Hello world'.

    Toutefois, si ta fonction retourne une structure contenant un tableau, il y aura recopie du tableau:
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    struct Message {
        char contenu[50];
    };
     
    struct Message gpp(void)
    {
        struct Message msg;
     
        msg.contenu[0] = '\0';
        strncat(msg.contenu, "Hello world", sizeof msg.contenu - 1);
     
        return msg;
    }
     
    int main(void)
    {
        struct Message message = gpp();
        printf("%s\n", message.contenu);
     
        return EXIT_SUCCESS;
    }
    NOTE IMPORTANTE: Pour des raisons de performance, il n'est pas recommandé de retournée une structure par copie comme présenté ci-dessus, surtout lorsque la taille du tableau est importante. On préfère en général l'approche de l'allocation dynamique.

    Thierry

  3. #23
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par PsychoH13 Voir le message
    Je t'ai dit que les fonctions nichées ne sont pas autorisées en C ANSI ou en C89, elles ne le sont quand C99.
    Tu as dit une ânerie.

    Les fonctions imbriquées ('nichée', je suppose que c'est du québécois) n'existent pas en C standard. C'est une extension de gcc que je ne conseille pas.

  4. #24
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Array Voir le message
    Une question bien idiote...
    De 2 choses l'une :
    • Soit c'est vraiment une question idiote, et j'efface le post,
    • Soit c'est une question, dans ce cas, ce n'est pas la peine de la qualifier d'idiote.
    J'aimerais savoir si l'on peut utiliser un tableau comme valeur de retour dans une fonction.
    C'est une question tout à fait pertinente et la réponse est non (détails dans la réponse de Thierry et compléments ci-dessous : ).

    http://emmanuel-delahaye.developpez....age=Page5#LXXV

  5. #25
    Membre du Club Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Points : 55
    Points
    55
    Par défaut
    Je vous remercie, Emmanuel & Thierry, pour la précédente réponse.

    Je fais face en ce moment à un autre problème, un problème de nombre à virgule. Tout d'abord, voici ce code :

    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
     
    #include <stdio.h>
     
    int funcn(float chiffre);
     
    int main(void) {
    	float vara, varb;
    	vara = 1.456;
    	varb = 2.9;
    	while (funcn(vara) == 1 || funcn(varb) == 1) {
    		vara *= 10.0;
    		varb *= 10.0;
    	}
    	return 0;
    }
     
    int funcn(float chiffre) {
    	printf("%f\n", chiffre);
    	while (chiffre > 1)
    		--chiffre;
    	if (chiffre > 0 && chiffre < 1)
    		return 1;
    	else
    		return 0;
    }
    Voici ce que ce programme écrit :
    Citation Envoyé par stdeq.exe

    1.456000
    14.559999
    145.599991
    1455.999878
    14559.999023
    145599.984375
    1455999.875000
    14559999.000000
    29000000.000000
    Ce que je voudrais élucider, c'est pourquoi le programme fait une soustraction dans le développement décimal de vara?

    En théorie, le programme devrait s'arrêter à 1456 pour vara et 2900 pour varb!!!

    Ça fausse tout!

    Comment me débarasser de ce comportement indésirable, pour ne pas dire ch***t!?

    Merci,

    Array

  6. #26
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Array Voir le message
    Je vous remercie, Emmanuel & Thierry, pour la précédente réponse.

    Je fais face en ce moment à un autre problème, un problème de nombre à virgule. Tout d'abord, voici ce code :

    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
     
    #include <stdio.h>
     
    int funcn(float chiffre);
     
    int main(void) {
    	float vara, varb;
    	vara = 1.456;
    	varb = 2.9;
    	while (funcn(vara) == 1 || funcn(varb) == 1) {
    		vara *= 10.0;
    		varb *= 10.0;
    	}
    	return 0;
    }
     
    int funcn(float chiffre) {
    	printf("%f\n", chiffre);
    	while (chiffre > 1)
    		--chiffre;
    	if (chiffre > 0 && chiffre < 1)
    		return 1;
    	else
    		return 0;
    }
    Voici ce que ce programme écrit :


    Ce que je voudrais élucider, c'est pourquoi le programme fait une soustraction dans le développement décimal de vara?

    En théorie, le programme devrait s'arrêter à 1456 pour vara et 2900 pour varb!!!

    Ça fausse tout!

    Comment me débarasser de ce comportement indésirable, pour ne pas dire ch***t!?

    Merci,

    Array
    Le problème avec les nombres à virgule flottante, c'est la précision. Certains nombres réels ne sont pas représentables exactement par un flottant de type float ou double. C'est notamment pour cette raison qu'on retrouver dans ta suite la valeur 14.559999 au lieu de 14.560000.

    Thierry

  7. #27
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    La situation peut être améliorée en utilisant des nombres flottants de type double à la place de nombres flottants de type float, et en modifiant l'algorithme utilisé dans la fonction funcn():

    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
    #include <stdio.h>
    #include <math.h>
     
    int funcn(double chiffre);
     
    int main(void)
    {
        double var_a = 1.456;
        double var_b = 2.9;
     
        while (funcn(var_a) == 1 || funcn(var_b) == 1)
        {
            var_a *= 10.0;
            var_b *= 10.0;
        }
     
        return 0;
    }
     
    int funcn(double chiffre)
    {
        int r_val = 0; /* return value */
        double precision = 1e-6;
     
        printf("%f\n", chiffre);
     
        if (fabs(round(chiffre) - chiffre) > precision)
        {
            r_val = 1;
        }
        return r_val;
    }
    La fonction round() est standard C99. Si ton compilateur ne supporte pas cette norme, il est relativement aisé de se construire sa propre fonction.

    Thierry

  8. #28
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    98
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 98
    Points : 87
    Points
    87
    Par défaut
    Etant nouveau sur le forum, je vous dis déjà bonjour à tous et je rassure Array ses questions ne sont pas bêtes mais fort interressantes pour le débutant que je suis également. De plus je pense qu'au delà la lecture du cours il est interressant de faire soit même des essais pour progresser.

    J'ai donc quelques questions :

    1ère situation :

    J'ai essayé la même chose que Array (enfin je pense) mais avec en renvoyant un pointeur sur une structure.

    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
     
    #include <stdio.h>
     
    struct structure{
    		int entier;
    		char lettre;
    	};
     
    struct structure *fonct(void){
    	struct structure s1;
     
    	s1.entier=5;
    	s1.lettre='a';
     
    	return &s1;
    }
     
    main(){
    	printf("Entier= %d\nLettre= %c\n",fonct()->entier,fonct()->lettre);
    }
    D'après les explications de thierry je m'attendais à ce que mémoire allouée localement pour la structure le soit sur la pile et que donc le pointeur retouné sur la structure pointe sur une adresse invalide à la sortie de la fonction pourtant la compilation et l'éxécution donnent chez moi le résultat attendu.

    Entier= 5
    Lettre= a

    Pourquoi ?

    2ème question :

    Je fais exatement la même chose qu'Array et alors j'ai bien une chaine "indéfinie" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include <stdio.h>
     
     
    char* fonct(void){
    	char s[6];
    	strcpy(s,"essai\0");
    	return s;
    }
     
    main(){
    	printf("Chaine= %s\n",fonct());
    }
    résultat :
    Chaine= ¼ ÿ¾öð

    Si maintenant dans ma fonction je fais un printf :

    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
     
    #include <stdio.h>
     
     
    char* fonct(void){
    	char s[6];
    	strcpy(s,"essai\0");
    	printf("Chainefonction= %s\n",s);
     
    	return s;
    }
     
    main(){
    	printf("Chaine= %s\n",fonct());
    }
    J'obtiens alors le résultat :
    Chainefonction= essai
    Chaine= essai

    Pourquoi es-ce que j'ai alors Chaine=essai ?

  9. #29
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    309
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 309
    Points : 380
    Points
    380
    Par défaut
    Pour commencer, quand tu écris
    Le \0 est intégré, inutile de mettre : "chaine\0". D'ailleurs ça risque même d'allouer une case en trop.

    À part ça, le fait de retourner l'adresse d'une variable locale est dangereux. Le truc c'est qu'à la fin de la fonction, toutes les variables locales à la fonction sont supprimées, mais quand on dit "supprimée" ça ne signifie pas "effacées" mais juste déréférencées, c'est-à-dire que si l'ordinateur n'a pas eu besoin de réutiliser la mémoire désallouée, il y a de fortes chances que le contenu de la mémoire soit le même ce qui fait que tu retrouves ton texte. Mais cela signifie aussi que l'ordinateur a pu réutiliser la mémoire libérée et dans ce cas ça chie...

    Dans tous les cas, à la fin d'une fonction, toute variable déclarée localement sont désallouées et sont donc considérées comme indéfinies. Une phrase à retenir en tant que programmeur (C tout au moins) : Tout ce qui est indéfini est à fuir comme la peste.

  10. #30
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par pmier Voir le message
    J'ai donc quelques questions :

    1ère situation :

    J'ai essayé la même chose que Array (enfin je pense) mais avec en renvoyant un pointeur sur une structure.
    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
     
    #include <stdio.h>
     
    struct structure{
    		int entier;
    		char lettre;
    	};
     
    struct structure *fonct(void){
    	struct structure s1;
     
    	s1.entier=5;
    	s1.lettre='a';
     
    	return &s1;
    }
     
    main(){
    	printf("Entier= %d\nLettre= %c\n",fonct()->entier,fonct()->lettre);
    }
    Stop ! Cette manip est absolument interdite. En effet, tu renvoies l'adresse d'une variable locale. Celle-ci est donc invalide après l'exécution de la fonction. Le comportement est indéfini. Tout peut arriver :

    http://emmanuel-delahaye.developpez....ge=Page8#LXLII

    Si j'ai bien compris, ça a été déjà expliqué. Ne pas chercher à vérifier le comportement indéfini, car par définition, il n'est pas défini donc invérifiable.

  11. #31
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par PsychoH13 Voir le message
    À part ça, le fait de retourner l'adresse d'une variable locale est dangereux.
    C'est un bug. Point.

    Le truc c'est qu'à la fin de la fonction, toutes les variables locales à la fonction sont supprimées, mais quand on dit "supprimée" ça ne signifie pas "effacées" mais juste déréférencées,
    Bip ! Confusion detectée !

    Utilises un autre mot. Il est déjà pris par l'opérateur '*' (dans un contexte 'pointeur' : '*' est l'opérateur de déréférencement).
    Une phrase à retenir en tant que programmeur (C tout au moins) : Tout ce qui est indéfini est à fuir comme la peste.
    C'est pire que ça. L'utilisation de ce qui est indéfini est un bug. Point.
    (et je ne pense pas que ce soit propre au C).

  12. #32
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    98
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 98
    Points : 87
    Points
    87
    Par défaut
    Merci à tous les 2

    Ok emmanuel, cela me fait mieux comprendre ce qu'est un comportement indéfini et je pourfendrai désormais ce type de comportement
    Je m'en vais de ce pas lire ton lien.

    Psycho : impecable ton explication tu m'as tout à fait convaincu et cela me parrait super logique merci.

    PS pour le dernier post d'emmanuel, oui j'avais fait la différence pour le mot déréférencé et aussi bizzard que cela puisse parraitre je n'arrive pas à admettre que "c'est comme ça". Il me faut une explication plausible

  13. #33
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par pmier Voir le message
    Psycho : impecable ton explication tu m'as tout à fait convaincu et cela me parrait super logique merci.
    Désolé de te ramener dans la réalité, mais il ne faut pas chercher de logique dans un comportement indéfini.

    La seule chose à retenir est qu'il ne faut pas qu'il y ait de comportement indéfini dans un code. Un seul suffit et le programme de 2.000.000 de lignes (bonne moyenne dans l'industrie pour les applications moyennes embarquées), est faux. Point.

    Il faut savoir qu'il n'existe aucun moyen automatique infaillible qui puisse détecter les comportements indéfinis. Seul l'oeil exercé d'un programmeur C entrainé et expérimenté peut le faire.

    Je rappelle une fois de plus que le C n'est pas un langage de débutant et que c'est une arme puissante mais tranchante. Ne manie pas le Bat'leth qui veux...

  14. #34
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    98
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 98
    Points : 87
    Points
    87
    Par défaut
    lol merci emmanuel.
    Le C n'est pas mon premier langage et je ne débute pas en informatique.

    Effectivement le C me parrai être un langage délicat, raison de plus pour tenter de le comprendre en profondeur et je continuerai malgré tes mises en garde de chercher à comprendre.
    Ceci dit contrairement a toi je ne tirerai aucune fiereté particulière lorsque je maitriserai mieux ce langage.
    Sur le fond ben ce n'est pas parce qu'un comportement est imprevisible qu'on ne peut pas comprendre pourquoi il en est ainsi.
    Même si on ne peut vérifier un comportement indéfini on peut le comprendre, ce n'est pas la même chose.

    Malgré tout je trouve tes interventions enrichissantes et ton site très intéressant parce qu'allant au fond des choses donc merci quand même.

    PS modère si tu le souhaite ce message qui n'a aucun intérêt!

  15. #35
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par pmier Voir le message
    Sur le fond ben ce n'est pas parce qu'un comportement est imprevisible qu'on ne peut pas comprendre pourquoi il en est ainsi.
    Même si on ne peut vérifier un comportement indéfini on peut le comprendre, ce n'est pas la même chose.
    Et quand le comportement indéfini se traduit par un comportement visible correct, tu en déduis quoi ? Si j'insiste comme ça, ce n'est pas par hasard...

  16. #36
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    98
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 98
    Points : 87
    Points
    87
    Par défaut
    Ben je n'en deduit rien bien sur puisque le comportement est in-de-fi-ni qu'il a dit le monsieur! Et contrairement a ce que je faisai au debut effectivement car selon l'explication precedente que j'avais mal compris le comportement ne me semblait pas indefini. Ceci dit le post de psycho m'a fait comprendre pourquoi le comportement n'etait pas defini. Il l'est car le systeme ecrase ou non la mémoire suivant des mécanismes plus compliqué (je sais pas si je suis clair!)

    J'ai bon ?

  17. #37
    Membre du Club Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Points : 55
    Points
    55
    Par défaut
    Eh bien, je te remercie pmier pour me rassurer en ce qui a trait à mes questions.

    Merci également à la réponsse enrichissante de Thierry.

    J'ai toutefois une autre question [lol].

    Dans la solution de thierry, quel est l'algorithme de "precision"?
    Autrement dit, que veux dire '1e-6'?

    Étant donné que mon prrogramme doit traiter des nombres à virgule pouvant aller jusqu'à un développement décimal de plusieurs dizaines de chiffres après le point, je crois que si je ne peux avoir des résultats totalement exact, je ferai ma propre librairie adaptée au prrogramme, avec des fonctions spéciales de manipulaations de chiffres à la virgule.

    Ceci dit, je vourais également savoir : Y a-t-il un moyen d'isoler une à une, un peux commee getchar() peut le faire avec les chaines de caractères, les valeurs d'une variable de type "integer" ou "float"?

    Par exemple, si j'avais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    main() {
    int i = 72543
    int c;
    c = fonction(i);
    printf("%d", c);
    }
    la variable c serait alors équivalente à "7".


    ???


    Merci,

    Array

  18. #38
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par pmier Voir le message
    Ben je n'en deduit rien bien sur puisque le comportement est in-de-fi-ni qu'il a dit le monsieur! Et contrairement a ce que je faisai au debut effectivement car selon l'explication precedente que j'avais mal compris le comportement ne me semblait pas indefini. Ceci dit le post de psycho m'a fait comprendre pourquoi le comportement n'etait pas defini. Il l'est car le systeme ecrase ou non la mémoire suivant des mécanismes plus compliqué (je sais pas si je suis clair!)

    J'ai bon ?
    Je ne comprends pas le sens de cette discussion. L'adresse d'une variable locale à une fonction devient invalide dès qu'on sort de cette fonction. Par la suite, il est interdit de déréférencer un pointeur contenant une adresse invalide. Point!

    Thierry

  19. #39
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Array Voir le message
    Étant donné que mon prrogramme doit traiter des nombres à virgule pouvant aller jusqu'à un développement décimal de plusieurs dizaines de chiffres après le point, je crois que si je ne peux avoir des résultats totalement exact, je ferai ma propre librairie adaptée au prrogramme, avec des fonctions spéciales de manipulaations de chiffres à la virgule.
    Pour te faire une idée de la précision atteignable avec un nombre flottant de type double (par exemple), la bibliothèque standard définit une constante DBL_EPSILON dans l'en-tête float.h. Cette constante représente la plus petite valeur x telle que 1.0 + x != 1.0. Sur ma machine, cette constante a une valeur de l'ordre de 2.2E-16.

    Voici une référence très instructive: What every computer scientist should know about floating-point arithmetic

    Thierry

  20. #40
    Membre du Club Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Points : 55
    Points
    55
    Par défaut
    Whew! 264 pages. Je n'y manquerai pas, étant donné que j'aime particulièrement jouer avec des nombres à virgule. Cependant, je vais attendre de finier de lire mon autre bouquin sur le C.

    Autrement dit, '1e-16' n'est pas vraiment un nombre . . .
    Ou plutôt ce n'est pas vraiment un algorithme.

    Cependant, une autre question fuse à l'instant dans ma tête :

    Est-il bien de tirer profit de la troncature des nombres entiers?
    Par exemple, si je veux avoir le développement décimal post virgule de 2.173 [qui est, évidemment, 0.173], est il bien de faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    #include <stdio.h>
     
    int main(void) {
    float x = 2.173
    int y;
    y = x;         /* "y" égalera à "2", avec la troncature */
    x = x - y;
    printf("%f", x);
    return 0;
    }
    Le programme écrira : 0.173
    Ce qui est bien!


    Aurait-il été mieux de trouver un autre moyen pour extraire 0.173 ?



    Merci,

    Array

Discussions similaires

  1. Réponses: 1
    Dernier message: 23/12/2007, 19h44
  2. Entrées.. Sorties.. quelques précisions..
    Par Djef-69 dans le forum SL & STL
    Réponses: 2
    Dernier message: 28/11/2007, 23h16
  3. [Fabrique] Quelques Précisions
    Par djflex68 dans le forum Design Patterns
    Réponses: 8
    Dernier message: 20/12/2006, 13h34
  4. Quelques "précisions" sur Struts
    Par Atma_ dans le forum Struts 1
    Réponses: 19
    Dernier message: 03/11/2006, 15h20

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