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 :

Conversion en C++ d'un cast C complexe


Sujet :

Langage C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Février 2003
    Messages
    44
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Février 2003
    Messages : 44
    Points : 49
    Points
    49
    Par défaut Conversion en C++ d'un cast C complexe
    Bonjour à tous !

    Je récupère dans mes projets du code en C qui permet d'accéder directement aux données contenues en mémoire. Typiquement il s'agit par exemple d'un tableau d'unsigned char qui est casté en unsigned int. C'est pas très clair, ça le sera peut être plus avec un exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    uint8_t tab[4] = {0x20,0x00,0x00,0x00};
    uint32_t val = *(uint32_t *)&tab;
    Après l'exécution de ce code, val contient 0x00000020, car on accède directement aux données en mémoire et donc on est tributaire de "l'endianess" de la machine (d'après ce que j'ai cru comprendre ) La raison principale d'utilisation de ce type de code étant sa vitesse, vu que contenu de val n'a pas besoin d'être byteswappé (dans le cas où on a besoin de récupérer la donnée sous cette forme, bien entendu...)

    Donc ma question est, existe-t-il un moyen de faire la même chose en C++ ? J'ai testé les casts dispo (static_cast, reinterpret_cast, etc. ) mais je n'ai pas réussi à avoir un code compilable

    Merci de votre attention

  2. #2
    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
    Salut,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    unsigned char tab[4] = {0x20,0x00,0x00,0x00};
    unsigned int val = *reinterpret_cast<unsigned char*>(&tab);
    mais il va de soit que c'est pas recommandé comme façon de faire

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Février 2003
    Messages
    44
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Février 2003
    Messages : 44
    Points : 49
    Points
    49
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Salut,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    unsigned char tab[4] = {0x20,0x00,0x00,0x00};
    unsigned int val = *reinterpret_cast<unsigned char*>(&tab);
    mais il va de soit que c'est pas recommandé comme façon de faire
    Effectivement, ça marche ... c'est bizarre, il me semblait avoir testé ce cas de figure hier, et d'avoir eu droit à une "syntax error" j'ai dû me manger un morceau

    Pour le fait que ce ne soit pas recommandé, je suis tout à fait d'accord, mais parfois le besoin de gagner en vitesse peut entrainer à faire des choses de ce type je suppose ...
    Tu aurais une idée sur comment arriver au même résultat de manière plus propre ?

    Quoiqu'il en soit, je te remercie pour ta réponse

  4. #4
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Runik Voir le message
    Tu aurais une idée sur comment arriver au même résultat de manière plus propre ?
    Pour avoir eu le cas concret, avec le même souci de performances, j'ai obtenu les éléments suivants :
    • Pose problème sur certaines architectures, où un accès non-aligné provoque un Bus Error (et donc un core dump).
    • Même sur un x86 (qui n'explose pas quand on le fait), les performances non-alignées sont fortement dégradées.
    • Il n'y a aucune méthode propre réelle sans passer par une structure supplémentaire.
    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef union {
      char char_data[4] ;
      int int_data ;
    } cast_union ;
    Il te faut alors remplacer l'usage de tes tableaux de char par l'usage du champ char_data de l'union précédente, et manipuler l'union elle-même en lieu et place du tableau de char.

    Cela demande en général une grosse refonte quand même, c'est donc rarement faisable à posteriori hélas...
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Février 2003
    Messages
    44
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Février 2003
    Messages : 44
    Points : 49
    Points
    49
    Par défaut
    C'est très intéressant ce que tu me dis là, je n'avais jamais vraiment cherché à savoir à quoi servait l'union, mais là j'en ai un bon exemple

    Par contre je me pose la question suivante : est-il possible, en utilisant une union, d'avoir à la fois la représentation inversée par octet sous forme d'entier (représentée par ton int_data), et la représentation d'un entier identique aux données saisies dans le tableau de char ?
    En gros si on définit par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    cast_union cu = { 0x12,0x34,0x56,0x78};
    cu.int_data sera égal à 0x78563412, mais est-il possible d'avoir aussi un entier égal à 0x12345678 sans avoir à faire de conversion coûteuse de char_data ?

    Merci de tes réponses en tout cas, j'aurai appris des trucs aujourd'hui

  6. #6
    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
    C'est vrai qu'il y a les problèmes d'alignement mais comme c'était issu de code C, j'ai supposé que ça marchait déjà.

    Citation Envoyé par Runik Voir le message
    Par contre je me pose la question suivante : est-il possible, en utilisant une union, d'avoir à la fois la représentation inversée par octet sous forme d'entier (représentée par ton int_data), et la représentation d'un entier identique aux données saisies dans le tableau de char ?
    Non. Dans une union, tous les champs partagent la même zone mémoire. Toi, tu veux modifier les octets de cette zone. Ce n'est pas possible.
    S'il te faut changer les structures, plutôt que passer par une union, construit directement un tableau d'entier ! Ce tableau de byte vient d'où ? Un datagram ? Une lecture de fichier ? En ce cas, 'typer' le contenu n'est peut être pas le plus coûteux de l'opération ?

  7. #7
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    La conversion n'a strictement rien de couteuse:

    Lorsque tu souhaite manipuler tes bytes sous la forme d'un int, tu accède simplement au champs int_data, et, lorsque tu souhaite les manipuler sous la forme de caractères, tu accède au champs char_data...

    Il faut bien comprendre que le but même de l'union est, tout simplement, de disposer de plusieurs variables de types potentiellement différents, mais utilisant une adresse mémoire commune et utilisant... l'espace mémoire nécessaire à la représentation de la variable la plus grande.

    A partir de là, si tu dois gérer les problèmes de boutismes, rien ne t'empêche de manipuler tes bytes sous la forme de... caractères, pour que les différents échanges soient répercutés sur l'entier:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int main()
    {
    cast_union cu={0x12,0x34,0x56,0x78};
    std::cout<<"before conversion : cu.int_data= 0x"
             <<hex<<cu.int_data<<std::endl;
    std::swap(cu.char_data[0],cu.char_data[3]);
    std::swap(cu.char_data[1], cu.char_data[2]);
    std::cout<<"after conversion : cu.int_data= 0x"
             <<hex<<cu.int_data<<std::endl;
        return 0;
    }
    aura comme sortie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    before conversion : cu.int_data= 0x78563412
    after conversion : cu.int_data= 0x12345678
    [EDIT]j'ai utilisé std::swap, mais on aurait tout aussi bien pu écrire un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // inversion des bytes 0 et 3
    cu.char_data[0]^=cu.char_data[3];
    cu.char_data[3]^=cu.char_data[0];
    cu.char_data[0]^=cu.char_data[3];
    //inversion des bytes 1 et 2
    cu.char_data[1]^=cu.char_data[2];
    cu.char_data[2]^=cu.char_data[1];
    cu.char_data[1]^=cu.char_data[2];
    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

  8. #8
    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 : 49
    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
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Il te faut alors remplacer l'usage de tes tableaux de char par l'usage du champ char_data de l'union précédente, et manipuler l'union elle-même en lieu et place du tableau de char.
    Je précise que ce genre de manipulations sur une union ne sont pas permises pas le C++, mais que certains compilateurs ont une extension qui l'autorise (visual C++, par exemple).
    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.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Février 2003
    Messages
    44
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Février 2003
    Messages : 44
    Points : 49
    Points
    49
    Par défaut
    @3DArchi : les données proviennent d'un gros tableau de unsigned char, représentant la mémoire d'une machine émulée

    @koala01 : merci pour tes précisions, en fait c'est ce que je fais actuellement en plus (en utilisant le cast C), c'est en voyant ton code que je m'en suis souvenu :p

    @JolyLoic : ben mince alors ... j'essaie de migrer mon code afin d'avoir quelquechose de portable tout en restant performant, et tu me dis qu'en fait la solution apportée n'est pas permise par le C++ ? Je suis déception
    J'utilise effectivement Visual Studio, mais ça signifie que mon code, une fois modifié, ne fonctionnera pas sur d'autres compilateurs ?
    Qu'est-ce qui n'est pas permis exactement ?

    Merci à tous pour vos réponses en tout cas

  10. #10
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Runik Voir le message
    J'utilise effectivement Visual Studio, mais ça signifie que mon code, une fois modifié, ne fonctionnera pas sur d'autres compilateurs ?
    Qu'est-ce qui n'est pas permis exactement ?

    Merci à tous pour vos réponses en tout cas
    Le code tel que je l'ai présenté fonctionne également sous Gcc ( MinGW en fait) 4.4.0 ...

    Mais, effectivement, la norme précise que seul l'accès au dernier champs de l'union modifié est garanti...

    Donc, si tu modifie, d'une manière ou d'une autre, le champs char_data dans les exemples précédents, seul l'accès à ce champs est garanti pour avoir... les valeurs indiquées et il n'est pas exclu que le champs int_data ait des valeurs aberrantes
    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

  11. #11
    Membre confirmé Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Points : 633
    Points
    633
    Par défaut
    Héhé, comique ça, c'est un problème d'alignement >< ! On y revient toujours finalement. Déjà
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef union {
      char char_data[4] ;
      long int_data ;
    } cast_union ;
    Devrait mieux passer. Je vois pas de cas ou ça pourrait foirer à l'optimisation. Mais c'est vrai que rien est garanti. Une classe méchante est peut être nécessaire >< !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct data{
    char char_data[4];
    operator long();
    };
    The mark of the immature man is that he wants to die nobly for a cause, while the mark of the mature man is that he wants to live humbly for one.
    --Wilhelm Stekel

  12. #12
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    @Lavock @ Mac LAK puis-je en profiter pour vous rappeler que le typedef n'est pas nécessaire (et même déconseillé) en C++

    Quel que soit le genre du type défini par l'utilisateur envisagé (class, struct, enum ou union), le fait de définir un type revient à ... l'enregistrer comme tel auprès du compilateur...

    Plutôt que d'écrire un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef union {
      char char_data[4] ;
      long int_data ;
    } cast_union ;
    qui travaille en deux temps:
    1. création d'une union anonyme
    2. définition du type cast_union comme étant l'union anonyme créée
    il est très largement préférable de directement utiliser le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    union  cast_union {
      char char_data[4] ;
      long int_data ;
    };
    qui ne passe pas par l'union anonyme
    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

  13. #13
    Membre confirmé Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Points : 633
    Points
    633
    Par défaut
    Au temps pour moi, je m'étais contenté de copier/coller le code de MacLak et de changer int en long >< !
    The mark of the immature man is that he wants to die nobly for a cause, while the mark of the mature man is that he wants to live humbly for one.
    --Wilhelm Stekel

  14. #14
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Il faut, en outre, être attentif à ne pas présumer de la taille des différents types dont on dispose...

    S'il est vrai que les implémentation "classiques" fonctionnant sur PC utilisent des int (et des long int) de 32 bits (ou plutôt de 4 bytes), ce n'est pas forcément le cas partout
    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

  15. #15
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Runik Voir le message
    mais est-il possible d'avoir aussi un entier égal à 0x12345678 sans avoir à faire de conversion coûteuse de char_data ?
    Hélas impossible, tu devras toujours faire appel à des fonctions de gestion d'endianness... Par contre, il faut savoir quand même qu'une BONNE fonction de gestion d'endianness ne fait absolument RIEN si tu es déjà dans le cas natif : typiquement, un hton sur une machine Big-Endian est une macro ne faisant absolument rien. Si tu définis des champs de bits, tu as aussi plusieurs pièges pouvant être bien velus (inversion de l'ordre des éléments du bitfield suivant l'endianness, notamment), donc attention.

    Citation Envoyé par JolyLoic Voir le message
    Je précise que ce genre de manipulations sur une union ne sont pas permises pas le C++, mais que certains compilateurs ont une extension qui l'autorise (visual C++, par exemple).
    C'est plutôt dépendant du processeur que du compilateur, en fait... En tout cas, aucun problème avec VS/Win32, GCC/Linux/x86, GCC/Linux/PowerPC et CC/Solaris/Sparc. Quel que soit le cas, ce genre de "truc" est bien évidemment à tester dans un programme de non-régression sur chaque nouvelle plate-forme, sinon, c'est vraiment chercher des bâtons pour se faire battre...

    Citation Envoyé par koala01 Voir le message
    @Lavock @ Mac LAK puis-je en profiter pour vous rappeler que le typedef n'est pas nécessaire (et même déconseillé) en C++
    J'ai horreur de me taper les "union" ou "struct" devant les noms d'identifiants, c'est pathologique...

    Citation Envoyé par koala01 Voir le message
    Il faut, en outre, être attentif à ne pas présumer de la taille des différents types dont on dispose...
    Je te rassures, c'est un cas ultra-simplifié que j'ai présenté. Mes unions "portables" (= gérant l'endianness et différentes tailles de mot-machine) sont certes pratiques et efficaces, mais soyons honnête : elles sont infectes à lire et à maintenir... Réservé au code très bas niveau dépendant de l'implémentation, donc.

    Citation Envoyé par koala01 Voir le message
    La conversion n'a strictement rien de couteuse:
    Si c'est une conversion de pointeurs, non, elle n'est pas coûteuse car résolue à la compilation. Mais si c'est un déréférencement, par contre, là ça peut faire très très mal... Cela va d'un léger overhead du temps d'accès (pour cause de non-alignement) jusqu'au Bus Error (spécialité des CPU Sparc, notamment). Le fait d'utiliser une union permet, justement, d'au moins s'affranchir du cas le plus pénible (le Bus Error) car le compilateur génère alors automatiquement le code ASM requis pour compenser, si c'est nécessaire... Ce qu'un cast sauvage avec déréférencement tout aussi sauvage ne permet pas.

    Bref, ce n'est pas coûteux de façon générale, mais cela peut devenir critique en fonction de l'architecture et/ou du niveau de performance requis.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  16. #16
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Si c'est une conversion de pointeurs, non, elle n'est pas coûteuse car résolue à la compilation. Mais si c'est un déréférencement, par contre, là ça peut faire très très mal... Cela va d'un léger overhead du temps d'accès (pour cause de non-alignement) jusqu'au Bus Error (spécialité des CPU Sparc, notamment). Le fait d'utiliser une union permet, justement, d'au moins s'affranchir du cas le plus pénible (le Bus Error) car le compilateur génère alors automatiquement le code ASM requis pour compenser, si c'est nécessaire... Ce qu'un cast sauvage avec déréférencement tout aussi sauvage ne permet pas.

    Bref, ce n'est pas coûteux de façon générale, mais cela peut devenir critique en fonction de l'architecture et/ou du niveau de performance requis.
    Etant donné que nous sommes dans un contexte d'utilisation d'une union, nous sommes bel et bien dans un contexte où cela n'a strictement rien de couteux, étant donné qu'il ne s'agit, ni plus ni moins, que d'indiquer à quoi un espace mémoire donné peut être utilisé, ce qui revient, finalement, à un cast C style ou au reinterpret_cast du C++...

    Et l'union subit exactement les mêmes restrictions que ces deux derniers, à savoir les éventuels problèmes que l'on peut rencontrer au niveau de l'alignement ou de la "mauvaise interprétation" des données, même si elle tend à rendre les conversions moins hasardeuses...
    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

  17. #17
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Et l'union subit exactement les mêmes restrictions que ces deux derniers
    Hé hé, justement, pas totalement... Sur un processeur ne gérant pas les données non-alignées, accéder à une union ayant des champs non-alignés ne cause aucune erreur, pour cause de code supplémentaire rajouté par le compilo. Alors qu'avec un cast / déréférencement, pas de code supplémentaire (ce qui est tout à fait normal d'ailleurs), et donc boum la tête si les données ne sont pas alignées.

    OK, c'est un cas vicieux, je sais, mais il existe. Cependant, il ne fait en fait que respecter la norme, qui n'a jamais dit qu'accéder à un champ valide d'une union dans une zone mémoire allouée pouvait provoquer un SIGBUS...

    On peut donc dire, de ce point de vue, que l'union est plus "safe" que les casts : sur les CPU type x86 ne posant pas de problèmes avec les données non-alignées, l'impact sur les performances est le même qu'avec un cast, ni plus, ni moins. Mais sur les CPU qui ne tolèrent pas ce genre d'accès, l'union marche là où le cast provoque une erreur. Elle ne subit donc pas TOUTES les restrictions applicables aux deux autres...
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  18. #18
    Membre du Club
    Profil pro
    Inscrit en
    Février 2003
    Messages
    44
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Février 2003
    Messages : 44
    Points : 49
    Points
    49
    Par défaut
    Merci à tous pour vos interventions, j'ai appris plein de choses et il me tarde de pouvoir les mettre en pratique

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

Discussions similaires

  1. [Casting] Echec de conversion
    Par femtosa dans le forum C++
    Réponses: 1
    Dernier message: 30/03/2007, 15h41
  2. conversion (cast) entre IntPtr int[]
    Par glebourg dans le forum C#
    Réponses: 2
    Dernier message: 29/03/2007, 10h03
  3. [Débutant] Deux questions sur la conversion (cast)
    Par kloss dans le forum Langage
    Réponses: 7
    Dernier message: 18/02/2006, 19h46
  4. - [CAST ou CONVERT] Problème de conversion de date
    Par Boublou dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 06/07/2004, 14h31

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