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 :

Conversion de données


Sujet :

C++

  1. #21
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    En même temps....
    Si on en est là... autant:
    1.a. Vérifier qu'on est sur une plateforme avec 'char = 8 bits' (mais c'est aussi valable pour l'union)
    1.b. Vérifier que unsigned long long int est un entier 64 bits (chez moi je préfère utiliser un truc genre __int64).
    2. Stocker les 8 chars dans un tableau
    3. La norme assurant que &(tableau[idx+1]) = &(tableau[idx]) + sizeof(element de tableau) [en l'ocurrence 1] alors on peut écrire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    char tab[8];
    // lecture du tableau
    tab[0] = 0x30; tab[1] = 0x89; ...
    // utilisation du tableau comme int64
    *((unsigned long long int*)tab) ...
    A noter que le code résultant est absoluement identique à l'utilisation de l'union (à mon avis plus propre).
    Mais il reste tout de même à vérifier les tailles des types avant.

  2. #22
    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
    A vrai dire, je ne suis pas particulièrement fanas des cast "sauvages", surtout s'il faut commencer par caster un tableau en un pointeur sur un autre type pour finir par... prendre l'élément pointé par ce pointeur...

    Tu me dira que c'est finalement exactement ce que fait l'union quand la taille des différents champs est calculée pour être identique, mais je reste malgré tout dans l'optique que c'est plus clair que le cast "sauvage"...

    En outre, cela présente l'avantage de nous laisser une certaine latitude sur le nombre de caractères fournis...

    En effet, le code (*(unssigned long long *)tab) serait fortement de nature à poser problème si, pour une raison ou une autre (l'incurie ou la distraction du programeur aidant), tab ne devait pas avoir été déclaré comme... un tableau de 8 char (sur base de la convention que l'on a décidé d'utiliser ici)...

    Par contre, je t'accorde effectivement le fait qu'il faudrait au minimum s'assurer du nombre de char entrant dans un unsigned long long (ou dans un __uint64), étant donné que la seule chose dont on soit sur, c'est que c'est un nombre entier de char
    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. #23
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par koala01 Voir le message
    En gros, elle interdit juste d'essayer de travailler sur plus d'un champs de l'union à la fois.
    Et ce que tu essaye de faire, c'est justement travailler sur plusieurs champs à la fois, puisque tu espère lire dans un des choses correspondant à ce que tu as écrit dans l'autre, et donc au moment de la lecture, tu suppose que les deux sont actifs simultanément.

    Le texte exact est :
    Citation Envoyé par Le standard
    In a union, at most one of the data members can be active at any time, that is, the value of at most one of the data members can be stored in a union at any time. [Note: one special guarantee is made in order to simplify the use of unions: If a PODunion contains several PODstructs that share a common initial sequence (9.2), and if an object of this PODunion
    type contains one of the PODstructs, it is permitted to inspect the common initial sequence of any of PODstruct members; see 9.2. ]
    Citation Envoyé par koala01 Voir le message
    Ainsi, tu ne pourrais pas envisager quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    union MyUnion
    {
        char chartab[8];
        long long mylong;
    }
     
    void foo()
    {
        MyUnion u;
        u.chartab[1]=0xff,u.mylong=0xFAFAFAFAFAFA;
    }
    Si, justement. Là, tu n'as pas pas supposé que deux champs étaient actifs simultanément, mais successivement. Donc pas de problème.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  4. #24
    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
    Pour le code que je donnais en exemple, je ne dis pas... par contre, je traduis peut être mal, mais, pour moi,
    , the value of at most one of the data members can be stored in a union at any time
    ca signifie
    la valeur de maximum un membre peut être stockée à chaque fois
    Il s'agit donc de l'acces en écriture aux membre, et non de l'acces en lecture...

    Il n'y a donc rien qui interdise, étant donné qu'un membre ne sera considéré actif que justqu'à la fin de l'instruction dans laquelle on l'utilise, de travailler sous une forme (désolé, je travaille encore avec un antique 32 bits)
    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
    union MyUnion
    {
        unsigned char tab[4];
        unsigned int entier;
    };
    int main()
    {
        MyUnion mu;
        mu.tab[0] = 0X40;
        mu.tab[1] = 0X40;
        mu.tab[2] = 0X40;
        mu.tab[3] = 0X40;
        cout<<hex<<mu.entier;
        return 0;
    }
    Je t'avouerai d'ailleurs que je n'arrive pas à trouver une situation (en mono-thread) dans laquelle les deux membres seraient actifs ne même temps...
    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

  5. #25
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    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 397
    Par défaut
    koala01: Mais là, tu accèdes à un champ que tu ne viens pas de stocker --> comportement indéfini, mu.entier est considéré comme non-initialisé.
    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.

  6. #26
    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
    Okay, je vois ou tu veux en venir...

    Mais, "considéré comme" non initialisé ne veut pas dire qu'il ne le soit pas forcément... et, dan le cas présent, il est effectivement initialisé (même si c'est de manière détournée, mais du simple fait du fonctionnement intrincèque de l'union)

    En outre, les unions pouvant avoir des fonctions et - dans le cas qui nous intéresse - plus particulièrement un constructeur, il est possible d'envisager d'en rajouter un qui initialiserait bel et bien le membre le plus long à 0

    Enfin, même si je sais que le "ça marche chez moi" ne doit pas inciter à tirer des conclusions, il se fait que... "ça marche chez moi", et cela donne exactement le résultat auquel je m'attendais

    Je t'avouerai, pour préciser les choses, que je ne suis pas particulièrement fana des unions, et que je suis donc *peut-etre* passé à coté de quelque chose...

    Je prend donc les remarques que l'on peut me faire sur le sujet d'un point de vue "didactique" (ce qui justifie quelque part mon insistance)

    Mais, à moins (et je ne demanderais pas mieux) que l'on m'explique (en dehors d'un "comportement potentiellement indéfini") clairement où mon raisonnement blesse, je trouve que l'union est sans doute de nature à apporter une sécurité supplémentaire par rapport à un transtypage sauvage, même si cette sécurité s'applique plus au transtypage (unsigned long) long ->char* qu'au transtypage char*-->(unsigned long) long.
    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. #27
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 762
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 762
    Par défaut
    A mon sens, les comportements indéfinis peuvent résulter du fait qu'il n'est pas possible de prédire l'ordre dans lequel le code (et le CPU) va charger les registres, ni la granularité des accès aux différents champs d'une union.
    => Les comportements peuvent varient en fonction du compilo et le CPU.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #28
    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 wiztricks Voir le message
    A mon sens, les comportements indéfinis peuvent résulter du fait qu'il n'est pas possible de prédire l'ordre dans lequel le code (et le CPU) va charger les registres, ni la granularité des accès aux différents champs d'une union.
    => Les comportements peuvent varient en fonction du compilo et le CPU.
    - W
    Je vais peut-être (surement ) avoir l'air buté, mais, je ne suis pas convaincu...

    En effet, le propre d'une union est de faire de manière à ce que tous ses membres utilisent le même emplacement mémoire, dont la taille est celle du membre le plus grand.

    Dés lors, tant que l'on travaille sur des type primitifs compatibles et assurant l'alignement des données, il ne devrait pas y avoir de problème.

    J'admets qu'une union du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    union MyUnion
    {
        struct Squeletton
        {
            unsigned char tail;  //8 bits (par convention)
            unsigned short middle; //16 bits (chez moi)
            unsigned char head; //8 bit;
        };
        Squeletton part;
        unsigned int entier; //32 bits (chez moi)
    };
    posera des problèmes, car l'alignement des données fait que la structure Squeletton ne fera pas 32 bits comme on pourrait s'y attendre, mais plutôt... (chez moi) 48 (), et que la taille "finale" de l'union sera dés lors de ...(toujours, chez moi) 64 bits (re )

    Par contre, si la base de réflexion est de se dire (histoire de pouvoir donner des valeurs précises):
    un unsigned long long prend la taille de 8 char consécutifs
    et que l'on crée une union dans laquelle l'un des membres est un "tableau de 8 char consécutifs", ainsi que je le propose avec mon fameux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    MyUnion
    {
        unsigned char tabchar[8];
        unsigned long long entier;
    }
    l'alignement des données est maintenu, que ce soit en mémoire ou en registre, et ce, même si un unsigned long long est trop grand pour tenir dans un seul registre...

    En effet, la priorité primordiale d'une union est que l'ensemble de ses membres utilisent le même emplacement mémoire, d'une taille égale au membre le plus grand.

    Dés lors, qu'il faille monopoliser un ou plusieurs registres pour y placer l'instance de l'union, ce seront les même instructions qui seront utilisée qu'il s'agisse d'y placer l'instance au départ de tabchar ou au départ d'entier...

    Et si une instruction demande de donner la valeur X au caractère se trouvant en 5 eme position, le compilateur devra de toutes manières prendre en compte le décalage nécessaire (que ce soit dans le registre ou directement en mémoire) permettant de dépasser les quatre premiers...

    Au final, je ne vois pas en quoi la granularité des membres de l'union ou l'ordre dans lequel le CPU la chargerait en registre serait de nature à apporter un comportement indéfini...

    Maintenant, comme je l'ai dit, il se peut que la logique que je suis ne soit pas correcte... mais alors, qu'on me dise où
    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

  9. #29
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Si j'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    union U {int i; char c};
     
    char f()
    {
        U u;
        u.i = 42; // <= Supprimable à l'optimisation
        return u.c;
    }
    Je m'attends à ce qu'un compilateur optimisant bien supprime l'écriture dans u.i, puisqu'il voit qu'elle ne sert à rien.

    Certains compilateurs ne le font peut-être pas, pour permettre plus de chose sur les unions que ce que permet la norme, mais ils seraient en droit de le faire.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  10. #30
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 762
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 762
    Par défaut
    L'exemple est un peu osé... Mais est une bonne illustration.

    Je pensais à des cas beaucoup plus tordus mais je n'ai pas encore trouvé d'exemple qui marche.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  11. #31
    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
    Merci JolyLoic... au moins, maintenant, je comprend où mon raisonnement blessait

    Mais, donc, si je comprend bien, avant de vouloir accéder - en lecture - "à l'autre membre" que celui auquel on vient d'accéder en écriture, il faut s'assurer d'avoir "validé" l'écriture pour que le compilateur ne soit pas tenté de supprimer une instruction qu'il jugerait sans effet
    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

  12. #32
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    En fait, il n'y a pas de moyen garanti par la norme de faire ce que tu veux (par contre, ton compilateur peut garantir plus, je crois que ce que tu veux faire est garanti par Visual C++, par exemple, car ils utilisent cette écriture dans certaines API windows). Pour avoir le droit de lire un membre d'une union, il faut :
    - Soit avoir écrit dedans auparavant, et ne pas avoir écrit dans un autre membre entre temps.
    - Soit être dans un cas particulier comme le suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    union U
    {
      struct T1 {int i; long j};
      struct T2 {int i; double d};
      T1 t1;
      T2 t2;
    };
    Tu as le droit de lire la partie i de t2 après avoir écrit t1.


    Pour ce qui est du problème initial, je préfère généralement travailler par décalage de bits, ce qui a aussi pour effet de me permettre de maîtriser simplement ce qui se passe, et de manière indépendante de la plate-forme, de son boutisme,... Et ce même dans les cas où l'écriture à base d'union marche.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

Discussions similaires

  1. Conversion de donnée
    Par elfyx dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 12/02/2007, 08h48
  2. Conversion de données
    Par noratec dans le forum Access
    Réponses: 3
    Dernier message: 17/03/2006, 17h50
  3. Conversion de données
    Par charliejo dans le forum C++Builder
    Réponses: 3
    Dernier message: 31/01/2006, 09h59
  4. Pb de conversion de données 16 vers 32
    Par Ducmonster dans le forum Langage
    Réponses: 2
    Dernier message: 09/10/2005, 11h53
  5. [JSTL] [SQL] Conversion de données
    Par GiHe dans le forum Taglibs
    Réponses: 4
    Dernier message: 27/09/2005, 10h01

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