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 :

[C++] Endianess char/short


Sujet :

C++

  1. #1
    Membre éprouvé
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Points : 1 067
    Points
    1 067
    Par défaut [C++] Endianess char/short
    Bonjour à tous!

    J'ai une fonction qui lit de la mémoire dans des registres et en renvoie le contenu. Cette fonction a cette forme simplifiée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool GetRegisterValue(const unsigned short &rusAddress, unsigned char *pucData, const unsigned long &rulSize);
    rusAddress est l'adresse du registre dans la mémoire
    pucData est un pointeur sur la zone mémoire qui va recevoir les données lues
    rulSize est la taille qui doit être lue en octets (taille du registre)

    Cette fonction a pour but d'être générique dans le sens où elle peut lire des registres de 8, 16 ou plus bits.

    Mon problème, c'est que je veux lire un registre de 16 bits, mais je dois passer un char*. Je fais donc un reinterpret_cast de mon short en char* et indique la taille 2.
    La lecture ne pose pas de problème, j'ai bien le bon retour, sauf que les 2 octets du short sont inversés (par rapport à la lecture via mon outil de validation).

    J'en déduis donc que j'ai un problème d'endianess. Est-ce que ça vient de mon reinterpret_cast? Comment faire autrement? Existe-t-il des fonctions en C++ comme htonl()/ntohl() pour winsocks (je développe sous VS2003)?

    NB: mon char fait 1 octet et mon short en fait 2.

    Merci d'avance
    "L'ordinateur obéit à vos ordres, pas à vos intentions." [Anonyme]

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Bizarre que tu aies des problèmes d'endianness dans ce contexte. C'est toi qui a écrit cette fonction ? Si non, d'où vient-elle ?

    Sinon niveau solution, il faut juste te faire une fonction qui inverse les octets si besoin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void SwapShort(short& x)
    {
        char b1 = (x & 0xFF00) >> 8;
        char b2 = (x & 0x00FF);
        x = b2 | b1;
    }

  3. #3
    Membre éprouvé
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Points : 1 067
    Points
    1 067
    Par défaut
    Non la fonction est issue d'un driver pour un bus de communications.

    J'ai compris mon problème, qui vient du fait que le driver ne me renvoie pas les octets d'un registre 16 bits dans le même ordre que celui du stockage d'un short dans la mémoire Windows.

    Je vais en fait passer un tableau de char que je reformaterais après la fonction, un peu comme tu me suggérais..

    Merci .
    "L'ordinateur obéit à vos ordres, pas à vos intentions." [Anonyme]

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Personnellement, je conseille des fonctions de ce style, qui marchent indépendamment de l'endianness du système :
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    #pragma once
    #include "Inline.h"
    #include "Casting.h"
     
    #ifndef COMPILE_TIME_ASSERT
    #define COMPILE_TIME_ASSERT(name, cond) typedef char COMPILE_TIME_ASSERT_ ## name [ (cond) ? 1 : -1 ]
    #endif
    /*
    "Standard" XtoYS functions :
    	Always work, regardless of current host endianness.
    	But, they may seem kind of slow, especially on big-endian hosts.
    */
    #ifdef _MSC_VER
    #pragma warning(push)
    #pragma warning(disable: 4204)//Non-constant agregate initializer (MS extension)
    #endif
     
    /*--- Big-Endian ---*/
    #pragma region Big-Endian
     
    static CCPP_INLINE UINT16 HtoBES(UINT16 h)
    {
    	UINT8 const c[2] = { HIBYTE(h), LOBYTE(h) };
    	COMPILE_TIME_ASSERT(SIZE, sizeof(c)==sizeof(h));
    	UINT16 const n = * REINTERPRET_CAST(UINT16 const *, &c);
    	return n;
    } 
     
    static CCPP_INLINE UINT16 BEtoHS(UINT16 n)
    {
    	UINT8 const * const c = REINTERPRET_CAST(UINT8 const *, &n);
    	UINT16 const h_high = c[0];
    	UINT16 const h_low = c[1];
    	return ((h_high << 8) | h_low);
    }
     
    static CCPP_INLINE UINT32 HtoBEL(UINT32 h)
    {
    	UINT8 const c[4] = { HIBYTE(HIWORD(h)), LOBYTE(HIWORD(h)), HIBYTE(LOWORD(h)), LOBYTE(LOWORD(h)) };
    	COMPILE_TIME_ASSERT(SIZE, sizeof(c)==sizeof(h));
    	UINT32 const n = * REINTERPRET_CAST(UINT32 const *, &c);
    	return n;
    } 
     
    static CCPP_INLINE UINT32 NtoBEL(UINT32 n)
    {
    	UINT8 const * const c = REINTERPRET_CAST(UINT8 const *, &n);
    	UINT32 const h_highhigh = c[0];
    	UINT32 const h_highlow = c[1];
    	UINT32 const h_lowhigh = c[2];
    	UINT32 const h_lowlow = c[3];
    	return ((h_highhigh << 24) | (h_highlow << 16) | (h_lowhigh << 8) | h_lowlow);
    } 
    #pragma endregion
     
    /*--- Little-Endian ---*/
    #pragma region Little-Endian
     
    static CCPP_INLINE UINT16 HtoLES(UINT16 h)
    {
    	UINT8 const c[2] = { LOBYTE(h), HIBYTE(h) };
    	COMPILE_TIME_ASSERT(SIZE, sizeof(c)==sizeof(h));
    	UINT16 const n = * REINTERPRET_CAST(UINT16 const *, &c);
    	return n;
    } 
     
    static CCPP_INLINE UINT16 LEtoHS(UINT16 n)
    {
    	UINT8 const * c = REINTERPRET_CAST(UINT8 const *, &n);
    	UINT16 const h_high = c[1];
    	UINT16 const h_low = c[0];
    	return ((h_high << 8) | h_low);
    }
     
    static CCPP_INLINE UINT32 HtoLEL(UINT32 h)
    {
    	UINT8 const c[4] = { LOBYTE(LOWORD(h)), HIBYTE(LOWORD(h)), LOBYTE(HIWORD(h)), HIBYTE(HIWORD(h)) };
    	COMPILE_TIME_ASSERT(SIZE, sizeof(c)==sizeof(h));
    	UINT32 const n = * REINTERPRET_CAST(UINT32 const *, &c);
    	return n;
    } 
     
    static CCPP_INLINE UINT32 NtoLEL(UINT32 n)
    {
    	UINT8 const * c = REINTERPRET_CAST(UINT8 const *, &n);
    	UINT32 const h_highhigh = c[3];
    	UINT32 const h_highlow = c[2];
    	UINT32 const h_lowhigh = c[1];
    	UINT32 const h_lowlow = c[0];
    	return ((h_highhigh << 24) | (h_highlow << 16) | (h_lowhigh << 8) | h_lowlow);
    } 
    #pragma endregion
     
    #ifdef _MSC_VER
    #pragma warning(pop)
    #endif
     
    /*Macros from "Network" byte order*/
    #define HtoNS HtoBES
    #define NtoHS BEtoHS
    #define HtoNL HtoBEL
    #define NtoHL BEtoHL
    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.

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

Discussions similaires

  1. [Langage] Boucle for : char, short VS int
    Par nschoe dans le forum Langage
    Réponses: 8
    Dernier message: 27/11/2008, 17h14
  2. Réponses: 15
    Dernier message: 12/06/2006, 12h03
  3. extraction de bits d'un short (ou d'un char)
    Par julie20 dans le forum C
    Réponses: 5
    Dernier message: 17/10/2005, 11h47
  4. Réponses: 1
    Dernier message: 13/10/2005, 15h10
  5. Réponses: 19
    Dernier message: 28/04/2005, 15h36

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