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

Langage C++ Discussion :

Conversions de type constants


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur

    Homme Profil pro
    Développeur PHP & Zend Framework 1 et 2
    Inscrit en
    Avril 2007
    Messages
    259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur PHP & Zend Framework 1 et 2
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 259
    Par défaut Conversions de type constants
    Bonjour,

    J'ai lu dans un livre que :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    const float pi = 3.1415;
    (float &) pi = 4;
    est possible en C++.

    Le livre n'expliquant pas pourquoi, j'aimerais comprendre.
    Comment si la variable est déclarer constante peut on la modifier avec un cast par référence.

    Pourquoi const_cast<float> pi = 4 ne fonctionne pas ?

    Quelqu'un peut il m'éclairer ?

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    le code est possible, mais n'aura normalement aucun effet...

    En effet, si tu demande l'affichage de pi après cette opération, tu devrais encore obtenir 3.1415

    La raison pour laquelle le code est accepté est simple: tu utilise un transtypage "C style" qui te permet strictement tout et n'importe quoi (il n'y a aucune vérification effectuée)...

    Cela te permettrait même de transtyper un F16 en bouquet de fleur, si tel était ton désir

    La raison pour laquelle le const_cast n'est pas accepté tel que tu le présente vient de deux erreurs de syntaxe.

    En effet, ce n'est pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const_cast<float> pi = 4;
    ni même
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const_cast<float>(pi) = 4;
    qu'il faut écrire (même si la deuxième syntaxe est déjà plus proche de la solution), mais bien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const_cast<float &>(pi) = 4;
    parce que const_cast demande que tu indique que le résultat soit une référence ou un pointeur.

    Cependant, le fait que la syntaxe soit acceptée ne veut absolument pas dire que l'instruction aura le moindre effet...

    En effet, l'affichage de pi après cette instruction devrait aussi être... 3.1415...

    (du moins c'est le cas chez moi)

    La raison de cet état de fait est, en définitive, relativement simple:

    Les variables constantes prennent place dans un segment de mémoire qui est "read only" (une fois que la valeur est déterminée, il est impossible de la modifier, et la seule utilisation possible de la valeur est... d'obtenir la valeur).

    Les deux exemples (cast C style et const_cast) dont il est question ici sont deux contre exemples qui consistent à "mentir" au compilateur pour lui faire croire qu'une valeur n'est pas constante et qui peuvent avoir des conséquences catastrophiques, ne serait-ce parce que, si tu ne vérifie pas correctement la valeur après l'instruction, tu risque de partir du fait que pi vaut...4, alors que ce n'est absolument pas vrai

    Ceci dit, et de manière générale, il s'agit de se méfier énormément de toute tentative de suppression de la constante d'un objet.

    En effet, tu auras le plus souvent eu de bonnes raisons pour décider qu'un objet (ou que la référence vers cet objet) devait être constant(e)...

    La raison principale étant sans doute que... tu souhaite restreindre les actions envisageables sur cet objet, pour t'assurer qu'il ne sera pas modifié.

    Le fait de supprimer cette restriction signifie finalement deux choses:
    • Soit que tu n'avais aucun besoin d'assurer la constance de l'objet
    • Soit que tu veux faire quelque chose qui posera problème en essayant malgré tout de modifier un objet qui n'a pas lieu de l'être
    Par contre, l'inverse (décider de transtyper un objet non constant en un objet constant) posera beaucoup moins de problème, parce que tu ne fait que rajouter des restrictions à son utilisation
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Rédacteur

    Homme Profil pro
    Développeur PHP & Zend Framework 1 et 2
    Inscrit en
    Avril 2007
    Messages
    259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur PHP & Zend Framework 1 et 2
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 259
    Par défaut
    Merci beaucoup pour cette réponse, ça commence a être déjà plus clair.

    Si je suis ton raisonnement (si j'ai bien compris ), le code ci contre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    const int a = 5;
    int & b = const_cast<int &> (a);
    b++;
    ne devrait pas modifié la valeur de a ?
    Pourtant l'affichage de a vaut 6 nan ?

    Sinon, la seule raison pour conts_cast d'exister et de pour pouvoir passer à une fonction qui demande un paramètre non constant une constante c'est ça ?

  4. #4
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Citation Envoyé par Koala01
    En effet, l'affichage de pi après cette instruction devrait aussi être... 3.1415...
    Koala, avec VS2005, ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    const float pi1 = 3.1415f;
    const float pi2 = 3.1415f;
    const float pi3  = 3.1415f;
     
    (float)pi1 = 4;
    (float&)pi2 = 4;
    const_cast<float&>(pi3) = 4;
     
    std::cout << pi1 << std::endl;
    std::cout << pi2 << std::endl;
    std::cout << pi3 << std::endl;
    affiche '4' dans tous les cas.
    Il semblerait qu'on ait affaire à un comportement indéfini.

  5. #5
    Rédacteur

    Homme Profil pro
    Développeur PHP & Zend Framework 1 et 2
    Inscrit en
    Avril 2007
    Messages
    259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur PHP & Zend Framework 1 et 2
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 259
    Par défaut
    Cela dépend alors si le compilateur place les constantes dans un "read only".

    La norme dit quelque chose à ce sujet ou elle le choix au compilateur de placer les const dans un "read only" ?

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Koala, avec VS2005, ce code :
    Avec gcc 4.4.1, sans activer le support de la nouvelle norme:
    refusé à la compilation (lvalue required as left operand of assignment )
    Y compris avec le support C++0x activé (j'aurais pensé que le lvalue references auraient pu changer quelque chose
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    (float&)pi2 = 4;
    const_cast<float&>(pi3) = 4;
     
    std::cout << pi1 << std::endl;
    std::cout << pi2 << std::endl;
    std::cout << pi3 << std::endl;
    affiche '3.1415' dans tous les cas.
    Il semblerait qu'on ait affaire à un comportement indéfini.
    Il semblerait en effet

    @fnnyaert >>Attention, on parle de deux choses tout à fait différentes...
    d'un coté, on crée une référence non nommée et non constante vers une variable constante, alors que de l'autre, tu crée une référence nommée mais non constante vers une variable constante

    Et là, nous en arrivons au comportement que je qualifiais de dangereux qui consiste à supprimer la constance d'un objet...

    Si le but est de modifier un objet constant, pourquoi diable avoir décrété qu'il ne devait pas être modifié

    Quant à savoir ce que dit la norme sur le sujet des références non nommées vers des objets constant, et sans avoir vérifié, je dirais sans doute que c'est un comportement indéfini, et donc particulièrement dangereux
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Rédacteur

    Homme Profil pro
    Développeur PHP & Zend Framework 1 et 2
    Inscrit en
    Avril 2007
    Messages
    259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur PHP & Zend Framework 1 et 2
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 259
    Par défaut
    Très bien merci j'ai compris !

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Parmi les facteurs contribuants à tel ou tel comportement, j'en vois deux:
    1. Si la constante est inlinée ou non:
      • Si elle est inlinée, les tentatives d'écriture, qu'elles agissent ou non sur la mémoire, ont des chances de laisser l'affichage inchangé parce que la valeur ne sera pas vraiment "lue".
      • Si elle n'est pas inlinée et qu'elle existe réellement en mémoire, une tentative d'écriture peut mener à une violation d'accès.
    2. où est déclarée la constante:
      • Variable globale: possibilité de déclaration en mémoire à lecture seule, risque de violation d'accès.
      • Variable locale: peut être déclarée simplement sur la pile.
    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.

  9. #9
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Euh :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    (int)var = somexp;
    ça compilera pas.. Y'a pas de lvalue à gauche. (un cast renvoie une r-value)

    edit : je faisais référence au message de arzar... mais en fait c'est plutôt une erreur de clavier qu'autre chose non?

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

Discussions similaires

  1. [DATE][CONVERSION] du type numerique au type date
    Par hamed dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 06/04/2005, 16h16
  2. Conversion de type
    Par sovitec dans le forum Langage
    Réponses: 5
    Dernier message: 15/12/2004, 14h29
  3. Conversion de type
    Par poirier dans le forum ASP
    Réponses: 2
    Dernier message: 06/07/2004, 10h30
  4. [MYSQL] conversion de type sur import de script
    Par sebos63 dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 27/08/2003, 10h00
  5. Réponses: 2
    Dernier message: 05/06/2002, 12h29

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