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 :

Adresse/offset du champs d'une structure


Sujet :

C

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7
    Points : 2
    Points
    2
    Par défaut Adresse/offset du champs d'une structure
    Bonjour,

    J'ai une structure avec des champs de differentes tailles. J'aimerais déclarer des 'defines' définissant l'offset de chacun des champs. Concrètement :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    typedef struct
      {
        tModbusFrame   RequestBuf;
        bool           FrameReceived;
        tModbusStatus  ModbusStatus;
        byte           NbReceiveErrors;
    } tModbusPort;
     
    #define MODBUS_STATUS_OFFSET      sizeof( tModbusFrame ) + sizeof( bool )
    #define NB_ERRORS_OFFSET          MODBUS_STATUS_OFFSET + sizeof( tModbusStatus)
    Le but des sizeof est de rendre les offsets independant de la cible (exemple, bool = 8 bits sur µcontrolleur, 16 bits sur pc).

    Quelqu'un aurait-il quelque chose de plus simple pour faire mes define (car ma vraie structure a une trentaine de champs...) ?

    Merci à tous.

    Ludo

  2. #2
    Membre Expert

    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juin 2003
    Messages
    4 506
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 506
    Points : 5 723
    Points
    5 723
    Par défaut
    Par curiosité ca te sert a quoi ? Parce que pour accéder un membre on fait MaGrosseStruct.champs1

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    En fait, la variable de type cette structure est locale à un fichier toto. J'accède aux champs depuis un fichier titi via des fonctions Read ou Write, prenant comme paramètre l'offset d'ecriture/lecture. Est-ce clair ?

  4. #4
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Voici comment je pratique:
    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
    #include <stdio.h>
    #include <stdlib.h>
     
    #define OFFSET_OF(type, membre) ((size_t) &((type *)0)->membre)
     
    struct Essai {
    	int x;
    	int y;
    	int z;
    };
     
    int main(void)
    {
    	size_t offset = OFFSET_OF(struct Essai, y);
     
    	printf("L'offset de z est %u bytes!", offset);
     
    	return EXIT_SUCCESS;
    }
    Ton implantation de MODBUS_STATUS_OFFSET par exemple n'est pas portable, car ne tient pas compte des éventuelles contraintes d'alignement. Ex:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct Essai {
        int x;
        char c;
        int y;
    };
    Sur ma machine, l'offset de y n'est pas de 5 bytes, mais de 8 bytes à cause de l'alignegnement des variables de type int sur des adresses multiples de 4.

    Thierry

  5. #5
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 957
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 957
    Points : 4 386
    Points
    4 386
    Par défaut
    vérifiez sur votre plate-forme si stddef.h définit offsetof(s,m) et/ou __offsetof(s,m)

    notez qu'en pratiquant de la sorte, si vous rendez votre code source compatible multi-environnement , les fichiers générés eux ne le seront pas…

  6. #6
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par ludo894
    En fait, la variable de type cette structure est locale à un fichier toto. J'accède aux champs depuis un fichier titi via des fonctions Read ou Write, prenant comme paramètre l'offset d'ecriture/lecture. Est-ce clair ?
    La sauvegarde d'une structure dans un fichier binaire est un problème délicat. As-tu un pouvoir de décision sur le format du fichier à utiliser pour stocker ta structure? Si tel est le cas, cet article est pour toi http://emmanuel-delahaye.developpez....m#enreg_struct

    Personnellement, j'aurais tendance à enregistrer une structure dans un fichier texte au format CSV (comma separated value), voir XML..

    Thierry

  7. #7
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    Par défaut
    Bonjour,

    G_STRUCT_OFFSET

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #define G_STRUCT_OFFSET(struct_type, member)	\
        ((glong) ((guint8*) &((struct_type*) 0)->member))

  8. #8
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Ta solution est interressante Thierry
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define OFFSET_OF(type, membre) ((size_t) &((type *)0)->membre)
    Le problème est que le calcul de l'offset se fait dynamiquement : j'aurais préféré un 'calcul' statique...

    Bien vu pour le probleme d'alignement : je viens justement d'avoir le bug !
    Ma structure est forcemment déclarée dans un .h.

  9. #9
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par ludo894
    Ta solution est interressante Thierry
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define OFFSET_OF(type, membre) ((size_t) &((type *)0)->membre)
    Le problème est que le calcul de l'offset se fait dynamiquement : j'aurais préféré un 'calcul' statique...

    Bien vu pour le probleme d'alignement : je viens justement d'avoir le bug !
    Ma structure est forcemment déclarée dans un .h.
    C'est pas dynamique, l'offset est calculé à la compilation. La solution de la glib proposée par gege est probablement encore plus portable. Je persiste à dire que ce n'est pas une bonne idée de vouloir sauver ta structure dans un fichier comme tu le fais.

    Thierry

  10. #10
    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
    Pourquoi chercher a definir une macro qui existe deja dans stddef.h et qui s'appelle alors offsetof?

    Sinon, les IO binaires se basant sur l'interpretation d'une structure C, on sait ce que ca donne: des bugs quand on change de flags de compilation, de version de compilateur, d'architecture ou d'OS.

  11. #11
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Oups, j'y suis allé un peu vite : effectivement c'est un 'calcul statique'...
    Pourquoi est-ce une si mauvaise idée de sauver ma structure dans un fichier ?

  12. #12
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Pourquoi chercher a definir une macro qui existe deja dans stdlib.h et qui s'appelle alors offsetof?
    Simplement parce que je l'ignorais! Merci pour le renseignement

    EDIT: c'est standard? C99?

    Thierry

  13. #13
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Pourquoi chercher a definir une macro qui existe deja dans stdlib.h et qui s'appelle alors offsetof?
    Perso cette macro n'est pas définie dans mon stdlib.h !

  14. #14
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par ludo894
    Oups, j'y suis allé un peu vite : effectivement c'est un 'calcul statique'...
    Pourquoi est-ce une si mauvaise idée de sauver ma structure dans un fichier ?
    En vrac:
    1) La représentation interne des données en C n'est pas fixée par la norme et peut varier d'une architecture à l'autre. La norme se contente de spécifier les valeurs extrêmes que doivent être capables de stocker chacuns des types.
    2) Les contraintes d'alignement
    3) L'endianesse (ça se dit ça). Sur certaines architectures, les données sont codées avec le byte de poids faible à une adresse inférieur à celle du byte de poids fort (little endian), et sur d'autres, c'est le contraire (big endian).

    Thierry

  15. #15
    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
    Citation Envoyé par ludo894
    Perso cette macro n'est pas définie dans mon stdlib.h !
    Desole, c'est dans stddef.h. (je corrige le message initial).

  16. #16
    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
    Citation Envoyé par mujigka
    EDIT: c'est standard? C99?
    C90, mais dans stddef.h et pas stdlib.h.

  17. #17
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Desole, c'est dans stddef.h. (je corrige le message initial).
    Verifié! Et en c'était disponible depuis C90...

    Il faut dire que je ne sers pas souvant de cette macro...

    Thierry

  18. #18
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par ludo894
    J'ai une structure avec des champs de differentes tailles. J'aimerais déclarer des 'defines' définissant l'offset de chacun des champs. Concrètement :
    C'est pas possible. Il faut utiliser une structure 'en dur', c'est à dire un tableau de unsigned char. C'est la seule façon d'être portable (indépendant de l'architecture). Les structures, c'est pour les données internes. Pas pour les interfaces physiques (flux).

    On peut automatiser ça à coup de macros. Faut maitriser...

  19. #19
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par ludo894
    Ta solution est interressante Thierry
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define OFFSET_OF(type, membre) ((size_t) &((type *)0)->membre)
    Le problème est que le calcul de l'offset se fait dynamiquement : j'aurais préféré un 'calcul' statique...

    Bien vu pour le probleme d'alignement : je viens justement d'avoir le bug !
    Ma structure est forcemment déclarée dans un .h.
    C'est du statique. Et c'est en fait la macro offsetof() qui est dans <stddef.h>

    Mais ça ne résout rien, ton code n'est pas portable.

    Je t'ai déjà donné une solution (enfin, le début)...

  20. #20
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    C'est pas possible. Il faut utiliser une structure 'en dur', c'est à dire un tableau de unsigned char. C'est la seule façon d'être portable (indépendant de l'architecture). Les structures, c'est pour les données internes. Pas pour les interfaces physiques (flux).

    On peut automatiser ça à coup de macros. Faut maitriser...
    La solution binaire (TLV ou XDR: http://emmanuel-delahaye.developpez....m#enreg_struct ) est-elle de manière générale à préférer à un fichier texte (du type CSV ou autre)? Le problème de l'encodage (ASCII) est-il une limitation importante d'un point de vue de la portabilité?

    Salutations

    Thierry

Discussions similaires

  1. Réponses: 4
    Dernier message: 07/03/2008, 16h40
  2. Comment écrire dans le champ d'une structure?
    Par JRmon42 dans le forum MATLAB
    Réponses: 2
    Dernier message: 04/04/2007, 12h16
  3. ordre des champs dans une structure
    Par oussema dans le forum C
    Réponses: 8
    Dernier message: 08/03/2007, 18h42
  4. Réponses: 4
    Dernier message: 10/04/2006, 09h28
  5. passer l'adresse d'un membre d'une structure ?
    Par tintin72 dans le forum C
    Réponses: 6
    Dernier message: 27/12/2005, 12h20

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