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 little-endian à big-endian et inversement


Sujet :

C++

  1. #1
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut Conversion de little-endian à big-endian et inversement
    Salut à tous !

    Je me retrouve à lire (en C++) des fichiers non formatés (binaires) séquentiels générés en Fortran, ce qui met à mal le peu de santé mentale qu´il me reste. Au-delà des problèmes de délimiteurs d´enregistrements que je pense avoir réglé, j´ai besoin de faire des conversions depuis petit-boutsien (little-endian) à gros-boutsien (big-endian) et inversement. Voici un code qui semble donner satisfaction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      /**
       * \brief Swap from little or big endian to the other.
       * \param x Data to be converted.
       * \todo This function has to be redone in a more secure way.
       */
      template <class T> inline void littleBigEndian (T &x) {
        // Number of bits for the swap. Infers that a char has 8 bits.
        const size_t n = sizeof(T) * 4;
        x = (x << n) | (x >> n);
      }  // void littleBigEndian (T &)
    Néanmoins, je crains qu´elle ne soit pas très sûr dans le cas de valeurs signées. De plus, je ne suis pas certain que ce soit le meilleur moyen d´effectuer cette conversion. Si quelqu´un s´est déjà attelé à ce problème et a des conseils, je suis preneur.

    À bientôt.

    Le Farfadet Spatial

  2. #2
    Membre éclairé

    Profil pro
    Inscrit en
    Mai 2005
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 264
    Points : 725
    Points
    725
    Par défaut
    Salut,

    Ton code me semble correct pour des entiers de 16bits, par contre, pour des entiers de 32 bits, il ne swappe pas tous les octets, mais seulement les deux mots de 16bits intermédiaires.

    Par exemple, l'entier 0x01020304 est stocké en mémoire comme :
    • 01 02 03 04 en big endian
    • 04 03 02 01 en little endian


    Or si je ne m'abuse (il est encore tôt et je ne suis pas encore à mon troisième café), ta fonction va transformer 01 02 03 04 en 03 04 01 02.
    "By and large I'm trying to minimize mentions of D in C++ contexts because it's as unfair as bringing a machine gun to a knife fight." - Andrei Alexandrescu

  3. #3
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    Si c'est pour des communications réseau tu peux utiliser htonl, ntohl....
    http://www.manpagez.com/man/3/htonl/

    Maintenant si tu as un appli qui tourne sur deux archi différentes et que tu passe des fichier de l'une a l'autre écrit en format binaire tu peux aussi les utiliser.

    Si c'est juste comment est fait la conversion le source est aussi dispo facilement trouvable sur le net:
    http://www.raspberryginger.com/jbail...eab285a1b46019
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

  4. #4
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut
    Salut à tous !

    Citation Envoyé par Niark13 Voir le message
    Or si je ne m'abuse (il est encore tôt et je ne suis pas encore à mon troisième café), ta fonction va transformer 01 02 03 04 en 03 04 01 02.
    Non, tu ne t´abuses pas, c´est bien ce qu´elle fait. Je suis allé un peu vite en besogne en imaginant que cela suffirait à la conversion quel que soit le type.

    Citation Envoyé par jabbounet
    Maintenant si tu as un appli qui tourne sur deux archi différentes et que tu passe des fichier de l'une a l'autre écrit en format binaire tu peux aussi les utiliser.
    Je suis dans ce dernier cas. Malheureusement, je ne peux pas être totalement certains que les en-têtes seront installés sur toutes les machines sur lequel le code doit être compilé, je ne peux donc pas simplement réutiliser les macro-commandes.

    Dans la mesure où il s´agit d´une conversion depuis des fichiers générés en Fortran, je n´ai à convertir que des entiers. J´ai donc repris le code pour créer cette fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
      /**
       * \brief Swap from little or big endian to the other.
       * \param x Data to be converted.
       * \todo It has to be redone in a more secure way.
       *
       * Infers that sizeof(int) == 4.
       */
      inline void littleBigEndian (int &x) {
        x = ((x >> 24) & 0xffL) | ((x >> 8) & 0xff00L) | ((x << 8) & 0xff0000L)
          | ((x << 24) & 0xff000000L);
      }  // void littleBigEndian (int &)
    Son effet à l´air d´être bien plus approprié que le précédent code. Cela dit, j´ai encore des doutes quant à sa validité sur des entiers signés : il me semble bien que, dans un tel cas, le résultat est fonction du compilateur.

    À bientôt.

    Le Farfadet Spatial

  5. #5
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par Le Farfadet Spatial Voir le message
    Je suis dans ce dernier cas. Malheureusement, je ne peux pas être totalement certains que les en-têtes seront installés sur toutes les machines sur lequel le code doit être compilé, je ne peux donc pas simplement réutiliser les macro-commandes.
    Ce n'est pas standard, mais c'est dans la librairie C Unix et Windows si je ne m'abuse donc en encapsulant ça correctement, ça devrait bien se passer (si ton contexte le permet)
    Find me on github

  6. #6
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut
    Salut à tous !

    Citation Envoyé par jblecanard Voir le message
    si ton contexte le permet
    Malheureusement non, le contexte ne me le permet pas (j´aurais préféré).

    À bientôt.

    Le Farfadet Spatial

  7. #7
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut
    Salut à tous !

    Bon, encore une mauvaise nouvelle pour ma raison chancelante : de toute évidence, il y a des différences d´encodages entre petit-boutsien et gros-boutsien également pour les nombres à virgules flottantes. Est-ce que quelqu´un a une idée de comment effectuer la conversion tant pour la simple précision que pour la double précision ?

    À bientôt.

    Le Farfadet Spatial

  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
    Dans le pire des cas, les différences d'encodage des flottants peuvent aller bien plus loin qu'une simple histoire de boutisme.
    Est-ce que tu es certain qu'il n'y a que ça ?
    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 confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut
    Salut à tous !

    Citation Envoyé par JolyLoic Voir le message
    Dans le pire des cas, les différences d'encodage des flottants peuvent aller bien plus loin qu'une simple histoire de boutisme.
    Est-ce que tu es certain qu'il n'y a que ça ?
    Certains, non.

    En revanche, je peux raisonnablement considérer que les nombres à virgules flottantes répondent à la norme IEEE 754. Dans un premier temps au moins, je pense qu´il est rentable de voir déjà la conversion entre petit et gros boutsien.

    À bientôt.

    Le Farfadet Spatial

  10. #10
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut
    Salut à tous !

    J´ai réussi à produire un code générique qui à mon avis est sécurisé :

    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
      /**
       * \brief Convert from little or big endian to the other.
       * \param x Data to be converted.
       */
      template <class T> inline void littleBigEndian (T &x) {
        // The new value.
        T tmp;
        // To interpret the value as an array of chars.
        unsigned char *toConvert = reinterpret_cast<unsigned char *>(&x);
        // The new value as an array of chars.
        unsigned char *converted = reinterpret_cast<unsigned char *>(&tmp);
     
        for (size_t i = 0; i < sizeof(T); ++i)
          converted[i] = toConvert[sizeof(T) - i - 1];
        x = tmp;
      }  // template <class T> void littleBigEndian (T &)
    Derrière, je fais confiance au compilateur pour produire un code optimisé (notamment pour dérouler les boucles).

    Dans mes tests, cela résout tous mes problèmes de conversion. Je passe le sujet en résolu, mais n´hésitez pas à dire si vous trouvez qu´il y a des défauts à ce code.

    Merci de votre aide.

    À bientôt.

    Le Farfadet Spatial

  11. #11
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    946
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 946
    Points : 1 351
    Points
    1 351
    Par défaut
    Salut,

    Citation Envoyé par Le Farfadet Spatial Voir le message
    il y a des différences d´encodages entre petit-boutsien et gros-boutsien également pour les nombres à virgules flottantes.
    Tout à fait. De mémoire, si tu convertis à l'aide de pointeurs petit* gros* et de swaps de bytes, tu peux appliquer la fonction de conversion autant aux flottants qu'aux entiers s'ils sont tous en 32 bits.

    A+

    Pfeuh

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

Discussions similaires

  1. Bibliothèque de conversion Little / Big endian ?
    Par BakaOnigiri dans le forum Bibliothèques
    Réponses: 2
    Dernier message: 21/12/2009, 14h17
  2. [Débutant] probleme compatibilité mac pc little et big endian
    Par tang97 dans le forum MATLAB
    Réponses: 2
    Dernier message: 14/02/2009, 10h07
  3. Réponses: 23
    Dernier message: 13/02/2009, 12h31
  4. Little endian - Big endian
    Par julinho99 dans le forum Ada
    Réponses: 4
    Dernier message: 10/04/2008, 11h13
  5. Conversion little vers big endian
    Par kris1980 dans le forum x86 32-bits / 64-bits
    Réponses: 8
    Dernier message: 16/08/2007, 13h42

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