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 :

Initialisation exotique d'une union


Sujet :

Langage C++

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1
    Points : 1
    Points
    1
    Par défaut Initialisation exotique d'une union
    Bonjour,

    Voici un bout de code qui compile avec gcc de version antérieure à 2.5
    (oui ca date)

    Ca ressemble à du C, mais c'est bel et bien compilé en C++.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    unsigned int i; 
    i = ((union toto_n {double d; unsigned int t[2];}){d:12.34}).t[1];
    on peut l'éclaircir un peu pour la compréhension:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    unsigned int i; 
    typedef union toto_n {
    	double d; 
    	unsigned int t[2];
    } toto_u;
     
    i = ((toto_u){d:12.34}).t[1];
    qui correspond au code, un peu plus à la norme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    unsigned int i; 
    typedef union toto_n {
    	double d; 
    	unsigned int t[2];
    } toto_u;
     
    toto_u x;
    x.d = 12.34;
    i = x.t[1];
    Enfin la on a une initialisation explicite de x, ce qui n'est pas le cas précédemment.

    Quelqu'un a-t-il déjà rencontré cette syntaxe d'initialisation d'un type union ?
    Je n'arrive pas à trouver mention nulle part de ce type de syntaxe...
    Toute information est la bienvenue !

  2. #2
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    double est codé sur 8 bytes.
    unsigned int sur 4 bytes.

    unsigned int[2] sera donc codé sur 2*4 bytes.

    Un union c'est tout simplement la même zone mémoire pour plusieurs variables, et la taille de l'union sera la taillé de son plus grand membre.

    Ici, ton union est codé sur 8 bytes, ce qui correspond à la taille de ses 2 membres. t[0] correspond aux 4 premiers bytes du double, et t[1] correspond aux 4 derniers bytes du double.

    Tu peux essayer ce code pour te donner une idée

    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 <iostream>
     
    int main()
    {
    	typedef union toto_n {
    		unsigned long long ull;
    		unsigned int ui[2];
    	} toto_u;
     
    	toto_u x;
    	char ll_c[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01 };
    	x.ull =*reinterpret_cast< unsigned long long* > ( &ll_c );
    	unsigned int i = x.ui[0]; // i = 0xFFFFFFFF
    	unsigned int j = x.ui[1]; // j = 0x1000000
     
    	std::cout << sizeof( toto_n ) << std::endl;
    	std::cout << std::hex << i << std::endl;
    	std::cout << std::hex << j << std::endl;
     
    }
    Edit: en relisant ta question, je me rend compte que je répond à côté de la plaque

  3. #3
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Bonjour et bienvenu,
    Je vais répondre à côté.
    Un mec qui te pond des lignes comme ça, il maîtrise peut être la syntaxe, mais il faut l'engueuler
    Le code doit garder une certaine lisibilité pour les personnes qui seront chargées par la suite de sa maintenance. Donc profiter de raccourcis syntaxiques pour écrire des lignes aussi courtes, ça n'est que créer des sources de confusions et de potentiels bugs.

    Accessoirement, ton code ne compile pas en GCC 4.3.3. Quand tu dis que tu compiles en C++, tu as un fichier d'extension .c ou .cpp ?

    En compilant avec GCC 4.3.3. en C en mode strict ansi, j'ai deux warnings :
    warning: obsolete use of designated initializer with ':'
    warning: ISO C90 forbids compound literals
    Ce qui tend à prouver que cette écriture est obsolète et peut être même plus acceptée par tous les compilateurs. Donc raison de plus pour l'oublier...

    Le premier est du à ce que tu utilises une variable membre de l'union pour spécifier dans la liste d'initialisation ce qui doit être initialisé. C'est l'équivalent de ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     union toto
     {
        int m_i;
        unsigned char m_uc[4];
     };
       union toto u = {m_i:5}; /* spécifier m_i génère le warning*/
     struct titi
     {
        int m_i;
        unsigned char m_uc[4];
     };
       struct titi u2 = {m_uc:{0,1,2,3}};/*l'utilisation de m_uc génère le warning*/
    La seconde pourrait se résumer à ce que tu utilises une variable non nommée et initialisée par une liste d'initialisation : (type){liste d'initialisation...}
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    struct point{int x;int y;};
    ((struct point){1,2}).x;// warning
    [EDIT] : au passage ce code n'est pas plus performant que celui qui serait plus verbeux.

  4. #4
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    Sinon, au niveau syntaxique, je ne peux que rejoindre l'avis de 3DArchi (sauf que chez moi, ça compile si je vire -ansi)

    C'est vraiment laid. Certains programmeurs codent littéralement de manière "encodée". Or, programmer c'est surtout un art de rendre les choses lisibles et facilement assimilables.

    Il t'a fallu combien de temps pour déchiffrer la ligne originelle ?

  5. #5
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Indépendamment de la lisibilité et de la conformité de l'initialisation dans le code original, le code ci-dessous a, sauf erreur de ma part, un comportement indéfini.

    Citation Envoyé par bber007 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    unsigned int i; 
    typedef union toto_n {
    	double d; 
    	unsigned int t[2];
    } toto_u;
     
    toto_u x;
    x.d = 12.34;
    i = x.t[1];
    Dans une union, seul le dernier membre mis à jour peut être lu (enfin sauf cas particuliers dans lesquels le code ci-dessus ne figure pas). La lecture de x.t après avoir valorisé x.d n'est donc pas un comportement spécifié par la norme et peut poser des problèmes sur certaines implémentations.

    Problème auquel il faut ajouter les différences de taille et d'endianness des types en fonctions de la plateforme.

    Bref le genre de code ultra-spécifique et totalement non portable qui peut être extrêmement utile dans certains cas mais qu'on rencontre le plus souvent utilisé à mauvais escient.

  6. #6
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Extension de gcc, obsolete depuis 2.5 -- la 2.6 est sortie il y a 15 ans! -- doc de gcc
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

Discussions similaires

  1. Initialisation d'une union
    Par enclair dans le forum C
    Réponses: 10
    Dernier message: 14/09/2010, 08h48
  2. initialisation static d'une liste
    Par maxvador dans le forum Langage
    Réponses: 6
    Dernier message: 13/10/2006, 10h29
  3. affectation d'une union
    Par Premium dans le forum C
    Réponses: 5
    Dernier message: 10/01/2006, 10h17
  4. Réponses: 6
    Dernier message: 13/11/2005, 12h11
  5. Réponses: 1
    Dernier message: 29/08/2004, 19h45

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