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 :

reinterpret cast qui ne fonctionne pas?


Sujet :

C++

  1. #1
    Membre régulier
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Points : 97
    Points
    97
    Par défaut reinterpret cast qui ne fonctionne pas?
    Bonjour tout le monde,

    j'ai besoin d'effectuer un cast sur des pointeurs,

    J'ai réalisé un programme de test, celui ci ne me donne pas le résultat escompté. 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
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    #include "stdafx.h"
    #include<iostream>
     
    using namespace std;
     
    int main()
     
    	float *b = new float;
    	double *c = new double;
     
    	*b = 100;
    	*c = 10;
     
    	b = reinterpret_cast<float*>(c); // je m'attends donc ici à ce que la valeur de *b soit 10;
     
    	cout << *b << endl;
    	cout << *c << endl;
     
        return 0;
    }
    Ici je m'attends à ce que *b et *c valent 10, or *b vaut 0.

    Savez-vous d'où vient mon erreur?

  2. #2
    Nouveau membre du Club
    Homme Profil pro
    Chomage
    Inscrit en
    Juillet 2016
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chomage

    Informations forums :
    Inscription : Juillet 2016
    Messages : 24
    Points : 33
    Points
    33
    Par défaut
    Bonjour ,
    dans ton reinterpret_cast<> , vous castez le pointer sur double en pointeur sur float , possible que ca profoque une erreur . apres ,essayez
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     *b = reinterpret_cast<float>(*c)
    car il est possible, je ne suis pas expert de ca , que le cast des pointeur , change le type du pointeur , mais pas la valeur pointée , et donc , lors de cout , le float du début ne peut plus s'afficher , car lors du transtypage vers un pointeur vers double , ca a reset l'addresse en mémoire , et donc la valeur de la valeur pointée est 0

  3. #3
    Membre régulier
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Points : 97
    Points
    97
    Par défaut
    Merci pour ta réponse Remilia!

    Alors j'ai tenté ta proposition elle ne fonctionne pas, cependant, en combinant ce que tu as écris et ce que j'ai compris des casts, j'ai réussi à trouver une commande qui me donne un résultat satisfaisant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    *b = static_cast<float>(*c);
    Je ne comprends cependant pas pourquoi ma première proposition ne fonctionnait pas : est ce que ca vient du fait que le compilateur réinterprète la suite de bit avec la commande reinterpret_cast ?

    Je ne comprends pas non plus nouveau point (dites moi si vous pensez que je dois ouvrir un nouveau thread) :

    Mon idée originelle était de créer deux variables de types differents : b et c. Je voudrais que ces variables aient toujours la même valeurs. SI a et b avaient été de même type, j'aurais fait par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int *b, *c;
    b=new int,
    c=new int;
    c= b;
    et tout le reste de mon programme, *b et *c auraient eu la mème valeur (si j'avais changé *b ou *c).

    Le problème est qu'ici je n'arrive pas à réaliser ça avec des variables de type différents et des static_cast...

    Avez vous une idée?

  4. #4
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Bonjour

    Tu peux utiliser une référence pour ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int b = 0;
    int & c = b;

  5. #5
    Membre régulier
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Points : 97
    Points
    97
    Par défaut
    Merci Ehonn,

    Cela fonctionne (avec la méthode des pointeurs), si b et c sont de même type... Si ils sont de type differents comment dois-je faire?

  6. #6
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Tu peux essayer quelque chose de ce goût là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    float a = 0.f;
    double & b = *reinterpret_cast<double*>(&a);
    Sinon, c'est peut être plus propre avec une union (?)

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Chomage
    Inscrit en
    Juillet 2016
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chomage

    Informations forums :
    Inscription : Juillet 2016
    Messages : 24
    Points : 33
    Points
    33
    Par défaut
    Et , effectivement , les différents "types" de casts sont les suivants :
    • static_cast<> : pour les conversions "standards", est la plupart du temps completement safe MAIS ne peut pas tout convertir
    • reinterpret_cast<> : reinterprete les octets de données , marche avec TOUT , mais est completement bourrin , ce qui , en cas d'erreur de logique , peut créer des résultats....surprenants voir corrompre des données (je convertis une std::string en int , ca.....va pas le faire)
    • const_cast<> : je ne vais pas l'expliquer , car son utilisation quasi démontre une erreur de conception

  8. #8
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Hello

    J'ai du mal à saisir quel genre de use case peut justifier de reinterpret_cast un double en float. C'est une très mauvaise pratique, qui à mon avis a un comportement indéfini par la norme. float n'est pas une abstraction de double, c'est un type complètement différent. Pour convertir de l'un à l'autre, il faut utiliser static_cast sur les valeurs et non pas les pointeurs.

    awawawa, à mon avis tu ne devrais pas utiliser de pointeurs du tout.
    Find me on github

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Tu ne peux pas espérer un résultat significatif en faisant un pointer-cast entre float et double, car (en IEEE) les deux ont des formats différents: En particulier, ils n'ont pas le même nombre de bits dans l'exposant, donc tronquer/"étendre par zero" la mantisse ne suffit pas!

    Franchement, le pointer-cast sur des float ou double, ça ne sert vraiment qu'à une chose: Afficher la représentation du nombre en binaire ou en hexadécimal (auquel cas on caste en int32_t et int64_t respectivement) ou à faire des calculs bizarres avec.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Membre régulier
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Points : 97
    Points
    97
    Par défaut
    Salut tout le monde,

    Tout d’abord je tiens vraiment à vous remercier pour votre réactivité et pour vos réponses.

    Supposons que je possède une classe dont l'une des donnée membre est redondante l'une des données qui existe dans une classe mère. Pas par défaut de conception mais plutôt par défaut de normalisation entres différentes APIs :

    Exemple je défini une classe voiture


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class voiture
    {
    int *nbPneus;
    }
    Que Renault maintenant me fournisse une API avec la fonction et la structure suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    structure Carracteristiques
    {
    float *NbRoues; 
    float *nbVolant;
    }
     Carracteristiques getCarracteritiques (void);
    Pour ne pas avoir a tout reprogrammer pour chaque constructeur, je peux imaginer créer une classe renault


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class renault:: publi voiture
    {
    structure Carracteristiques
    {
    float *NbRoues; 
    float *nbVolant;
    }
     
     Carracteristiques getCarracteritiques (void);
     
    private :
     
     Carracteristiques mCarracteritiques
    }




    J'aimerais qu'à l’intérieur de la classe Renault, la condition mCarracteristiques.NbRoues ==Nbroues soit toujours verifiée.

    D'où ma demande

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Pas faisable avec un pointeur.

    PS: Caractéristique ne prend qu'un seul R.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Quelque chose me frappe : pourquoi diable utilises-tu des pointeurs partout ? Du reste compter un nombre de roues et de pneus avec un nombre flottant est quelque peu étrange. Peux-tu avoir 1,5 roues ? Un entier ferait mieux l'affaire .

    Pour en revenir à la généralité de ton problème, ce que tu cherches à faire, c'est maintenir un invariant. De mon point de vue, il n'y a aucune raison d'encapsuler Caracteristiques dans Voiture, et aucune raison de dupliquer les données. Si tu ne dupliques pas, ton problème d'invariant ne se posera pas.

    Si tu dois mélanger des classes qui ont des incohérences d'API entre elles, alors tu peux cacher cela et fournir des fonctions membres d'accès qui ne modifieront les données qu'en assurant l'invariant.
    Find me on github

  13. #13
    Membre régulier
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Points : 97
    Points
    97
    Par défaut
    Merci jblecanard et merci...Médinoc


    J'ai pris le nombre de pneus, j'aurais pu prendre le niveau d'huile : supposons que Toyota me le donne en float et Renault en double

    Je préfère garder la structure de chez Renault dans la classe Renault car elle contient des données propres à ce constructeur, non accessibles à l'utilisateur lambda (qui a accès seulement aux données de la classe voiture), mais qui pourront être utiles en cas de diagnostic, par exemple.

    Si tu dois mélanger des classes qui ont des incohérences d'API entre elles, alors tu peux cacher cela et fournir des fonctions membres d'accès qui ne modifieront les données qu'en assurant l'invariant.
    Je pense que je vais faire ça au final : c'était ma première idée, mais je me suis dit que pointer le même emplacement mémoire me permettrait de ne pas me soucier des mises à jours des valeurs de ces variables

  14. #14
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Comme dit plus haut, float et double n'ont strictement rien à voir binairement parlant, donc espérer avoir la même valeur pointée en castant de la sorte c'est totalement impossible.
    Globalement, caster des trucs qui n'ont pas la même taille à coup de reinterpret faut être certain de ce que l'on fait.
    Soit c'est n'importe quoi, soit tu cherches à utiliser le static_cast sans le savoir ?
    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.

  15. #15
    Membre régulier
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Points : 97
    Points
    97
    Par défaut
    Re re re merci tout le monde

    Effectivement...

    Ce que j'aurais aimé, pour être plus concis, c'est


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    float *a;
    double *b;
    Et maintenir la condition *a==*b pendant toute l'exécution du programme sans avoir à se soucier des mises à jour de *a lorsque *b est changé et vice versa. Du coup je me suis dit : que a et b pointent sur le meme emplacement mémoire[...] (certes il aurait pu avoir un problème de débordement dans un cas mais passons)

    D'après vos retours ce n'est pas possible...

  16. #16
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    À mon avis la bonne solution reste l'utilisation des références (c'est fait pour ça).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    float a = 0;
    float & b = a;
    L'équivalent avec des pointeurs serait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    float v = 0;
    float * const a = &v;
    float * const b = &v;
    Après pour l'interprétation double en tant que float, soit tu sais vraiment ce que tu fais et tu joues avec reinterpret_cast, soit tu prends en compte les messages précédents à ce sujet.

    Citation Envoyé par awawawa Voir le message
    D'après vos retours ce n'est pas possible...
    En fait, en encapsulant ça dans une classe, ça va être possible d'avoir « *a == *b » (suffit de surcharger l'opérateur unaire *) (dans un contexte mono-thread).
    On peut te le montrer (pour la pédagogie) mais, promis, ce n'est pas " ce que tu veux ".

  17. #17
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Ehonn, tes conseils ne vont pas s'appliquer car awawawa cherche à appliquer cet invariant sur un double un un float, pas sur deux float ou deux double.

    Citation Envoyé par awawawa Voir le message
    (certes il aurait pu avoir un problème de débordement dans un cas mais passons)

    D'après vos retours ce n'est pas possible...
    awawawa, les nombres à virgule flottante ne sont pas encodés comme des entiers, ce n'est pas un problème de débordement que tu vas avoir, mais pire ! Il faut comprendre ce que tu fais. reinterpret_cast est violent et son usage correct nécessite que tu connaisses précisément comment les données sont représentées en mémoire. Ce n'est pas un reproche, mais tout porte à croire que ce n'est pas le cas. reinterpret_cast est inadapté à ton besoin. Tu devrais plutôt utiliser des références et des static_cast.
    Find me on github

  18. #18
    Membre régulier
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Points : 97
    Points
    97
    Par défaut
    Merci tout le monde,

    Je laisse ce thread ouvert. Je prendrai un peu de temps ce weekend pour tester 2 - 3 choses et je reviens vers vous avec mes conclusions


  19. #19
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 580
    Points
    218 580
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Pourquoi ne pas utiliser un variant (style QVariant, ou Boost::variant) ?
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  20. #20
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Honnêtement, une classe unique, avec un setter/getter pour float, un autre pour double, qui stocke tout en double en interne et cast quand nécessaire, ça me parait le plus judicieux.
    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.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Code qui ne fonctionne pas sur Mac
    Par malbaladejo dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 14/01/2005, 11h08
  2. [SQL] Requête à jointure qui ne fonctionne pas
    Par Bensor dans le forum Langage SQL
    Réponses: 2
    Dernier message: 09/12/2004, 16h10
  3. Jointure externe qui ne fonctionne pas
    Par Guizz dans le forum Langage SQL
    Réponses: 3
    Dernier message: 05/02/2004, 12h26
  4. CREATEFILEMAPPING qui ne fonctionne pas???
    Par Jasmine dans le forum MFC
    Réponses: 2
    Dernier message: 06/01/2004, 19h33
  5. UNION qui ne fonctionne pas
    Par r-zo dans le forum Langage SQL
    Réponses: 7
    Dernier message: 21/07/2003, 10h04

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