Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème de compréhension des unions

Sujet résolu
    16 juin 2018 à 21:42:51

    Bonjour,

    J'ai un peu de mal à comprendre pourquoi cette union arrive à garder les deux dernières affectations dans la même mémoire.

    union myUnion
    {
        int a;
        double b;
    };
    
    int main()
    {
        myUnion x;
        x.a = 4;
        std::cout << x.a << "\n";
        std::cout << x.b << "\n\n";
    
        x.b = 8.78;
        std::cout << x.a << "\n";
        std::cout << x.b << "\n\n";
    
        x.a = 47;
        std::cout << x.a << " (" << &x.a << ")\n";
        std::cout << x.b << " (" << &x.b << ")\n";
        return 0;
    }

    En compliant, j'obtiens ceci

    4
    2.05192e-307
    
    687194767
    8.78
    
    47 (0x6dfef8)
    8.78 (0x6dfef8)

    Comment cela se fait-il que j'obtiens les bonnes valeurs (aux deux dernières affectations) pour chaque attribut alors qu'ils ont le même emplacement mémoire ?

    • Partager sur Facebook
    • Partager sur Twitter
      17 juin 2018 à 1:04:27

      Tu te fais troller par la compilation. Remplaces "double" par "float" pour avoir des types de meme taille memoire et tu verras ce que ca fait.

      Cf http://en.cppreference.com/w/cpp/language/union 

      The details of that allocation are implementation-defined, 
      and it's undefined behavior to read from the member of the union that wasn't most 
      recently written. Many compilers implement, as a non-standard language extension, 
      the ability to read inactive members of a union.

      Donc en gros, ne fais pas ça. (Le C++ est un langage permissif, il t'autorise à écrire du code non valide, qui fait n'importe quoi. C'est à toi de faire attention à ne pas faire ces erreurs)

      • Partager sur Facebook
      • Partager sur Twitter
        17 juin 2018 à 10:08:00

        Bonjour,

        Merci pour ta réponse. En effet, avec deux attributs de même taille, les valeurs non initialisées sont perdues à chaque fois.

        En revanche j'ai toujours du mal à comprendre pourquoi.

        Many compilers implement, as a non-standard language extension, 
        the ability to read inactive members of a union.

        Comment le compilateur peut-il implementer le fait d'avoir deux valeurs différentes sur un même emplacement mémoire ? Cela me parait impossible... Car même s'ils utilisent une taille mémoire différente, cela doit quand même affecter l'autre attribut, non ?

        -
        Edité par seba110298 17 juin 2018 à 10:09:42

        • Partager sur Facebook
        • Partager sur Twitter
          17 juin 2018 à 12:49:59

          Ajoutes au début :

          std::cout << std::cout.precision(50);

          Ca va peut etre t'aider a comprendre. (aide : regarde comment son représenté les doubles en memoire)

          • Partager sur Facebook
          • Partager sur Twitter
            17 juin 2018 à 13:09:33

            Bonjour Gbdivers et Seba110298 :

            à quoi sert cette ligne :

            std::cout << std::cout.precision(50);

            J'ai fait une petite recherche, pas bien saisi à quoi ça sert.

            • Partager sur Facebook
            • Partager sur Twitter
              19 juin 2018 à 17:13:27

              Bonjour,

              Ok je pense avoir compris grâce à ce support.

              Lorsque l'on met un double en mémoire, la mantisse se trouve à la droite de l'emplacement mémoire (un double constitué de 64 bits dont 52 bits pour la mantisse situés le plus à droite de l'emplacement mémoire) et une fois qu'on a trouvé la valeur de la mantisse (après avoir normalisé et pris la valeur décimale en binaire), on remplit le reste de l'emplacement mémoire de la mantisse avec des zéros, à droite de la valeur (ces valeurs n'étant finalement pas utilisé).

              Je suppose donc qu'au lieu de mettre les valeurs non utilisées situées à droite de la mantisse à 0, le compilateur les ignore simplement ? Ce qui fait que pour un int, les valeurs commençant par les bits non utilisés de la mantisse ne seront pas affectées ?

              Est-ce que mon raisonnement est juste ?

              J'espère avoir été assez clair dans mon explication.

              Merci encore pour votre aide

              • Partager sur Facebook
              • Partager sur Twitter
                19 juin 2018 à 18:24:05

                Presque. Les bits sont utilisés, mais ils correspondent aux chiffres tres loin apres la virgule. Et par defaut, std::cout n'affiche pas tous ces chiffres. Et donc effectivement, quand tu les modifies avec l'union, tu ne vois pas ces changement, du fait que std::cout arrondi les chiffres. Et std::precision affiche ces chiffres, ce qui permet de voir le changement.

                Note, tu peux aussi utiliser std::bitset pour afficher la représentation binaire des nombres, pour bien voir le résultat.

                • Partager sur Facebook
                • Partager sur Twitter
                  22 juin 2018 à 10:26:41

                  Merci pour l'explication. Je comprends mieux maintenant :)
                  • Partager sur Facebook
                  • Partager sur Twitter

                  Problème de compréhension des unions

                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                  • Editeur
                  • Markdown