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 :

Une question sur le stockage des variables


Sujet :

C

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 4
    Points : 2
    Points
    2
    Par défaut Une question sur le stockage des variables
    Bonjour,
    J'ai un petit soucis de compréhension sur la façon dont son stockées les variables dans la mémoire vive. A priori si je créer un variable de type long, je ne devrais pas pouvoir stocker de nombre décimal, or avec un code tout simple j'obtient une valeur décimale dans une variable de type long.

    Voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    double Nombre3 = 0;
    double Nombre4 = 0;
    double ResultatDivision = 0;
    long ResultatDivisionEntier = 0;
     
    printf("Faisons une division de nombres decimaux \nTaper le numerateur :");scanf("%lf", &Nombre3);
    printf("Taper le denominateur :");
    scanf("%lf", &Nombre4);
    ResultatDivision = Nombre3 / Nombre4 ;
    ResultatDivisionEntier = Nombre3 / Nombre4 ;
    printf("Le resultat est %lf \n", ResultatDivision);
    printf("Le resultat (partie entiere) est %lf", ResultatDivisionEntier);
    et voici ce qui s'affiche :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Faisons une division de nombres decimaux
    Taper le numerateur : 5
    Taper le denominateur : 2
    Le resultat est 2.500000
    Le resultat (partie entiere) est 2.500000
    Comment est-ce possible d'avoir "Le resultat (partie entiere) est 2.500000", alors que ResultatDivisionEntier est un long ?

    J'ai essayé en simplifiant (oui encore) le programme et en mettant que la partie concernant le resultat entier. Ca donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    double Nombre3 = 0;
    double Nombre4 = 0;
    long ResultatDivisionEntier = 0;
     
    printf("Faisons une division de nombres decimaux \nTaper le numerateur :");scanf("%lf", &Nombre3);
    printf("Taper le denominateur :");
    scanf("%lf", &Nombre4);
    ResultatDivisionEntier = Nombre3 / Nombre4 ;
    printf("Le resultat (partie entiere) est %lf", ResultatDivisionEntier);
    et le Résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Faisons une division de nombres decimaux
    Taper le numerateur : 5
    Taper le denominateur : 2
    Le resultat (partie entiere) est 0.000000
    Autrement dit, cette fois-ci c'est cohérent puisqu'il ne reconnait pas ResultatDivisionEntier comme un nombre décimal.

    Alors si quelqu'un comprend ce qui se passe je suis preneur d'une explication !!
    Merci

    Bien sur ce programme n'a aucun intérêt, mais ça me paraît dérangeant de réserver un emplacement mémoire pour un entier et d'en retirer un décimal.:
    roll:

  2. #2
    Membre Expert

    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juin 2003
    Messages
    4 506
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 506
    Points : 5 723
    Points
    5 723
    Par défaut
    Cela ne viendrait pas du fait que tu utilises comme spécificateur de format %lf ? On ne devrait pas utiliser ce spécificateur pour un long ? D'autant plus que le compilateur ne doit pas pouvoir détecter ce genre d'erreur. J'imagine(pas testé) que tu pourrais utiliser %s pour afficher un long...Ce qui n'a pas de sens à mon goût.(Comportement indéfini de printf dans ce cas ? )

  3. #3
    Membre éclairé Avatar de crocodilex
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    697
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 697
    Points : 858
    Points
    858
    Par défaut
    Citation Envoyé par UnReveDeCryptomeria
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("Le resultat (partie entiere) est %lf", ResultatDivisionEntier);
    Simplement parceque tu dis d'afficher un flottant.
    Essayes plutôt avec %ld

  4. #4
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut
    Avec quel compilo as-tu travaillé ?
    D'abord, j'ai fait une modif dans ton programme
    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
    #include <stdio.h>
     
    int main(void)
    {
    	double Nombre3 = 0;
    	double Nombre4 = 0;
    	double ResultatDivision = 0;
    	long ResultatDivisionEntier = 0;
     
    	printf("Faisons une division de nombres decimaux \nTaper le numerateur :");scanf("%lf", &Nombre3);
    	printf("Taper le denominateur :");
    	scanf("%lf", &Nombre4);
    	ResultatDivision = Nombre3 / Nombre4 ;
    	ResultatDivisionEntier = Nombre3 / Nombre4 ;
    	printf("Le resultat est %lf \n", ResultatDivision);
    	printf("Le resultat (partie entiere) est %lf\n", (double) ResultatDivisionEntier);
     
      return 0;
    }
    Il faut en effet mettre transformer la valeur de ResultatDivisionEntier en double pour avoir un résultat correct sinon tu fais afficher n'importe quoi.
    Avec Visual C6 j'ai un warning à la compilation
    warning C4244: '=' : conversion from 'double ' to 'long ', possible loss of data
    et comme résultat pour 5 et 2 : 2,5 et 2 ce qui est normal.
    Si j'enlève le cast en double j'obtiens pour les mêmes valeurs 2,5 et 0.

  5. #5
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    Par défaut
    Citation Envoyé par hegros
    D'autant plus que le compilateur ne doit pas pouvoir détecter ce genre d'erreur. J'imagine(pas testé) que tu pourrais utiliser %s pour afficher un long...Ce qui n'a pas de sens à mon goût.(Comportement indéfini de printf dans ce cas ? )
    Si avec la bonne configuration, gcc vérifie ce genre de chose (compatibilité entre le spécificateur de format et le type de la variable ainsi que le nombre d'arguments)

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Comme je l'ai dit ce programme n'a aucun intérêt, il met juste en évidence le prolème, à savoir qu'il m'affiche un double alors que je lui demande d'accéder à une zone mémoire où se trouve un long, comment est-ce possible ?
    Le %lf est utilisé consciemment puisque je lui demande un double, alors que je lui fourni un long, c'est justement pour montrer qu'il le fait, alors qu'il ne devrait pas.
    A mon avis il doit s'emmêler les pinceaux dans l'adressage mémoire puisque dans le second cas il fonctionne correctement, mais comment ça se fait ?

    J'utilise l'IDE code::blocks.

    Je sais pas s'il y a une explication logique et qui s'emmêle les pinceaux ; le proce, le compilateur, ou une logique de fonctionnement du langage C ?

    Et puis je n'en mourrais pas puisqu'en temps normal, on ne fait ce genre de chose.

  7. #7
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par UnReveDeCryptomeria
    Comme je l'ai dit ce programme n'a aucun intérêt, il met juste en évidence le prolème, à savoir qu'il m'affiche un double alors que je lui demande d'accéder à une zone mémoire où se trouve un long, comment est-ce possible ?
    Le %lf est utilisé consciemment puisque je lui demande un double, alors que je lui fourni un long, c'est justement pour montrer qu'il le fait, alors qu'il ne devrait pas.
    A mon avis il doit s'emmêler les pinceaux dans l'adressage mémoire puisque dans le second cas il fonctionne correctement, mais comment ça se fait ?

    J'utilise l'IDE code::blocks.

    Je sais pas s'il y a une explication logique et qui s'emmêle les pinceaux ; le proce, le compilateur, ou une logique de fonctionnement du langage C ?

    Et puis je n'en mourrais pas puisqu'en temps normal, on ne fait ce genre de chose.
    C'est le programmeur qui s'emmêle les pédales... Toute information est donnée par une séquence plus ou moins longue de bits. Rien à voir avec le type de la zone mémoire, toute case mémoire peut servir à un moment donné pour des caractères, pour des entiers, pour n'importe quoi...

    Tu lui donnes une séquence de bits et tu lui dis que c'est des flottants, il devrait l'interpréter suivant la norme qu'il a pour les flottants. Un point c'est tout... Mais il ne le fait pas sinon tu aurais un nombre qui n'a rien à voir avec 2.5...

    Alors pourquoi est-ce qu'il t'affiche le même résultat? Parce que ton processeur a des registres dédiés aux nombres flottants et que le compilateur n'a pas changé l'état des registres flottants donc printf récupère la dernière valeur d'un de ces registres et il se trouve que c'est le même que celui qui contient le 2.5 de l'instruction précédente...

    Mais comme dit, si tu avais compiler correctement tu aurais eu :

    part.c:17: warning: format ‘%lf’ expects type ‘double’, but argument 2 has type ‘long int’
    Et c'est donc au programmeur de corriger le code...

    Jc

  8. #8
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Ok, pour les zones mémoires, c'était pas clair ce que j'ai écrit...

    Tu veux dire qu'il récupère le dernier nombre flottant stocké ? pourtant j'ai essayé le code suivant pour vérifier :

    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
    double Nombre3 = 0;
    double Nombre4 = 0;
    double NombreTest = 0;
    long ResultatDivisionEntier = 0;
     
    printf("Faisons une division de nombres decimaux \nTaper le numerateur :");
    scanf("%lf", &Nombre3);
    printf("Taper le denominateur :");
    scanf("%lf", &Nombre4);
    NombreTest = 8.452;
    printf("Le nombre test est %lf\n", NombreTest);
    ResultatDivisionEntier = Nombre3 / Nombre4 ;
    printf("Le resultat (partie entiere) est %lf", ResultatDivisionEntier);
     
    return 0;
    ce qui me donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Faisons une division de nombres decimaux
    Taper le numerateur : 5
    Taper le denominateur : 2
    Le nombre test est 8.452000
    Le resultat (partie entiere) est 8.451996
    C'est a rien y comprendre, où est-ce qu'il va chercher ce nombre ?
    Et si j'enlève la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("Le nombre test est %lf\n", NombreTest);
    il me met :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Le resultat (partie entiere) est 0.000000
    Sinon je suis aussi d'accord sur le fait que c'est au programmeur de corriger cette incohérence, malheureusement le compilateur de code::blocks ne donne pas d'alerte. Et le résultat est tout de même surprenant. va falloir que je me trouve un schéma qui me permette de faire le lien entre les requêtes d'un programme et les actions d'écriture/lecture d'un proce en mémoire vive.

    Merci pour les réponses en tout cas !!

  9. #9
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Si tu enlèves le premier printf, il ne mettra pas le flottant dans le registre flottant donc printf ne le trouvera pas pour le 2ème appel... Rien de surprenant...

    Pour Code::blocks, tu peux ajouter les options du compilateurs. Voir le forum sur les EDI...

    Jc

  10. #10
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Je crois que c'est presque résolu du coup ! Merci pour tes lumières fearyourself !
    Il reste plus que cet écart de 4 dans le nouvel exemple 8.452000 et 8.451996. D'où peut-il venir ?

  11. #11
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par UnReveDeCryptomeria
    Il reste plus que cet écart de 4 dans le nouvel exemple 8.452000 et 8.451996. D'où peut-il venir ?
    Vu que tu fais des choses non conforme, le compilateur ne passe pas les bons paramètres en place, ne met pas les bons registres en place pour le bon fonctionnement de printf.

    Donc cette différence est dû à une corruption d'état du registre (sûrement) flottant contenant la valeur du premier printf...

    Jc

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 15/07/2008, 14h43
  2. Une question sur le nom des contrôles
    Par mouaa dans le forum VBA Access
    Réponses: 4
    Dernier message: 25/01/2008, 16h30
  3. Une question sur les « Names » des objets.
    Par phdnet dans le forum W4 Express
    Réponses: 7
    Dernier message: 04/12/2007, 08h54
  4. Réponses: 4
    Dernier message: 04/06/2006, 16h53
  5. Réponses: 2
    Dernier message: 22/04/2006, 18h18

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