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 :

Pb macro offsetof


Sujet :

C++

  1. #1
    Membre averti
    Inscrit en
    Mars 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 29
    Par défaut Pb macro offsetof
    Salut à tous,

    Je souhaite connaitre l'offset d'un attribut contenu dans un objet qui lui même et contenu dans un tableau d'objet.

    Concrétement voilà une description qui marche avec un tableau statique :

    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
    class CVoiture 
    {
         int matricule;
    }
     
    class CParcking
    {
        CVoiture listeParking[1];
    }
     
    void maFonction()
    {
        CParcking park;
        park.listeParking[0].matricule = 1234AA33;
     
        size_t pos = offsetof(CParcking, listeParking[0].matricule);    
    }
    Dans le cas précédent, je récupère bien l'offset recherché.
    Mais lorsque je souhaite utilisé un tableau dynamique, cela ne marche pas comme dans l'exemple suivant :

    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
    class CVoiture 
    {
         int matricule;
    }
     
    class CParcking
    {
        CVoiture *listeParking;
    }
     
    void maFonction()
    {
        CParcking park;
        park.listeParking = new CVoiture[1];
        park.listeParking[0].matricule = 1234AA33;
     
        size_t pos = offsetof(CParcking, listeParking[0].matricule);    
    }
    En effet, je constate l'exception "Acces violation location"

    Donc est il possible d'utiliser la macro offsetof pour référencer un tableau dynamique sinon y a t il un autre procédé ?

    Merci pour votre aide

  2. #2
    Membre émérite Avatar de Caine
    Inscrit en
    Mai 2004
    Messages
    1 028
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 028
    Par défaut
    Bonjour,

    offsetof réclame un type structure en argument.

    Regarde cet exemple:

    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
     
     
    #include<stdlib.h>
    #include <stdio.h>
    #include <stddef.h>
    #include <iostream.h>
     
    class Car {
    	public:
    		char Matricule[15];
    		char CarType[15];
    		Car(char *aMatricule,char *aType);
          Car();
    };
     
    Car::Car() {
    	memset(Matricule,15,0);
     	memset(CarType,15,0);
    }
     
    Car::Car(char *aMatricule,char *aType) {
    	memcpy(CarType,aType,15);
    	memcpy(Matricule,aMatricule,15);
    }
     
    int main() {
     
    	Car Voiture("235 XXL 24","Luxe");
     
    	Car *Voitures = new Car[1];
     
    	memcpy(Voitures[0].Matricule,"144 FGH 56",15);
    	memcpy(Voitures[0].CarType,"Coupe",15);
     
    	Voitures[1]= Voiture;
     
    	printf("%s\n",Voiture.CarType);
     
    	printf("offsetof : %d\n", offsetof(Car,CarType));
     
       system("pause");
       return 0;
    }
    offsetof renvoie l'octet où débute un champ de structure donné, c'est une macro, donc tu dois lui passer le type.

    PS: merci d'utiliser les balises code, ça aide la lisibilité.

  3. #3
    Membre averti
    Inscrit en
    Mars 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 29
    Par défaut
    Suite à ta remarque j'ai plassé des balise code qui effectivement facilite la visibilité.

    Concernnant le problême, j'ai effectué le petit test et malgré tout il passe bien par le if et non le else. Grace à mon debugger je vois bien que le new crée bien mon objet et l'instancie donc le problème vient bien du offset.

    Aurais tu une autre suggestion ?

  4. #4
    Membre émérite Avatar de Caine
    Inscrit en
    Mai 2004
    Messages
    1 028
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 028
    Par défaut
    Arf, je viens justement de revoir mon message!

    Tout est dans la nouvelle réponse après essais.

  5. #5
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        park.listeParking = new CVoiture[1]; 
      ....
        size_t pos = offsetof(CParcking, listeParking[0].matricule);
    offsetof ne peut donner un résultat correct : A cause de l'allocation dynamique, listeParking[0].matricule est à une adresse qui n'a rien à voir avec celle du CParcking. Les CVoiture ne sont pas dans la mémoire allouée à la classe CParcking et seule l'adresse de listeParking a un sens par rapport à CParcking.
    Ceci est différent du cas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class CParcking 
    { 
        CVoiture listeParking[1];  
    }
    où les CVoiture (et leurs éléments) sont dans la mémoire allouée à la classe CParcking

  6. #6
    Membre averti
    Inscrit en
    Mars 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 29
    Par défaut
    Ton exemple Caine marche sans problème mais mon souci est que souhaite que l'objet CarType dans ton exemple soit un tableau dynamique listeParking dans mon exemple
    qui contienne des attributs et c'est ces attributs que je souhaite référencer dans l'offsetof tout en me basant sur l'objet CParcking.

    Comprends tu mon souci ?

  7. #7
    Membre averti
    Inscrit en
    Mars 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 29
    Par défaut
    Merci diogene pour ton eclaircissement.

    Alors dans ce cas je ne peut utiliser offsetof et donc y aurait il un autre moyen de connaitre l'offset de l'objet souhaité ?

  8. #8
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    y aurait il un autre moyen de connaitre l'offset de l'objet souhaité ?
    Dans ce cas, il faut préciser l'offset par rapport à quoi. Le seul offset qui peut avoir un sens est celui par rapport à la valeur contenue dans listeParking , c'est à dire par rapport au début du tableau. Il est alors possible de trouver l'offset d'un membre de CVoiture par rapport à cette origine :
    listeParking[i] possède un offset de et celui du membre matricule par rapport à CVoiture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    offsetof(CVoiture, matricule);
    L'offset de listeParking[i].matricule est alors
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    i*sizeof(CVoiture)+offsetof(CVoiture, matricule)
    toujours par rapport au début du tableau.
    Il est possible ici d'utiliser offsetof parce que ce terme sera résolu à la compilation. (offsetof ne peut être résolu à l'exécution. L'impossibilité de sa résolution à la compilation entrainait l'erreur "Acces violation location" à l'exécution , sujet de ton post). sizeof également

  9. #9
    Membre averti
    Inscrit en
    Mars 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 29
    Par défaut
    Merci Diogene, j'avance sur la voie

    Malgré tout si je me base sur mon premier exemple j'ai un décalage du calcul de l'offset entre mon calcul et le tien.

    Avec cette méthode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    size_t pos = offsetof(CParcking, listeParking[0].matricule);
    Je trouve un résultat de l'odre de 608

    Avec ta méthode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    size_t pos = i*sizeof(CVoiture)+offsetof(CVoiture, matricule)
    Je trouve un résultat de l'odre de 288

    Il y a un décalage de 320 et si je rajoute un décalage de 320 au deuxieme calcul, j'ai le bon offset et dans la suite de mon programme je tappe bien la bonne donnée
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    size_t pos = i*sizeof(CVoiture)+offsetof(CVoiture, matricule)+320
    D'ou vient ce décalage ? je n'ai pas réussi à le déterminer

  10. #10
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    D'ou vient ce décalage ? je n'ai pas réussi à le déterminer
    On ne prend pas dans les deux cas l'offset par rapport à la même chose :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    size_t pos = offsetof(CParcking, listeParking[0].matricule);
    prend pour origine le début de la structure CParcking
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    size_t pos = i*sizeof(CVoiture)+offsetof(CVoiture, matricule)
    prend comme origine le début du tableau des CVoiture. La valeur doit donc être plus faible puisque qu'il manque l'offset du début du tableau par rapport au début du CParcking . La différence doit être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    offsetof(CParcking, listeParking);
    Note : Les chiffres obtenus 288 , 608 semblent indiquer que ces structures sont plus complexes que l'exemple que tu cites dans ton premier post.
    Si tu utilises un tableau non dynamique , la première expression est plus simple et l'origine de l'offset peut être logiquement le début de la structure CParcking ou le début du tableau au choix. Si ton tableau doit être dynamique, prendre comme origine de l'offset le début de la structure CParcking n'a pas de sens

  11. #11
    Membre averti
    Inscrit en
    Mars 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 29
    Par défaut
    J'ai compris pour le tableau statique, cela donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    size_t pos = offsetof(CParcking, listeParking) + i*sizeof(CVoiture)+offsetof(CVoiture, matricule)
    J'avais oublié l'offset pour aller au debut du tableau.

    Mais dans ce cas je comprend pas comment faire avec un tableau dynamique en me basant au départ de CParking car dans ce cas ce n'est plus le parcours i*sizeof(CVoiture).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    size_t pos = offsetof(CParcking, listeParking) + ????? +offsetof(CVoiture, matricule)
    Comment me positionner sur le bon Ieme objet CVoiture avec un tableau dynamique ?

  12. #12
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Mais dans ce cas je comprend pas comment faire avec un tableau dynamique en me basant au départ de CParking car dans ce cas ce n'est plus le parcours i*sizeof(CVoiture).
    Je ne sais pas ce que tu veux faire ni pourquoi tu veux calculer ces offset. Pour les tableaux dynamiques, l'offset par rapport à CParking n'a pas de sens (ils n'appartiennent pas à la même structure de données et non même pas de structure commune) et on va tenter de faire de la jonglerie à faire hurler les puristes (qui n'auront pas tort ). Enfin, essayons et faisons le gros dos parce qu'on va avoir des réflexions désobligeantes de nos pairs auquelles on sera bien en peine de répondre.
    On peut calculer l'offset par rapport au début du tableau dynamique
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    i*sizeof(CVoiture)+offsetof(CVoiture, matricule)
    . On "connait" l'adresse de départ de l'instance x de CParcking (ca va dépendre de l'instance de classe et ce ne sera plus un invariant) : (size_t)&x. On "connait" l'adresse de départ de ce tableau puisqu'elle est dans listeParking : (size_t)(x.listeParking ). On arrive à une horreur du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (size_t)(x.listeParking )+i*sizeof(CVoiture)+offsetof(CVoiture, matricule)-(size_t)&x
    Je dégage toute responsabilité et suis honteux d'avoir écrit tout ça . D'ailleurs, je ne suis pas sur que le compilateur accepte de le faire.

  13. #13
    Membre averti
    Inscrit en
    Mars 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 29
    Par défaut
    Merci Diogene pour toutes tes explications, j'ai vraiment avancé dans la compréhension de mon problème.

    Malheureusement ta dernière solution marcherait normalement dans le contexte de mon exemple mais dans mon cas concret plus complexe, le calcul du offset se passe dans une fonction à part qui est static ce qui empêche l'utilisation du x.

  14. #14
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    comment faire avec un tableau dynamique en me basant au départ de CParking
    J'insiste une dernière fois : Calculer un tel offset me semble être un non-sens total . Que peut-on faire d'une telle "information" ? A quoi peut-elle servir ? Tu utilises un langage de "haut niveau" pour obtenir des informations du plus bas niveau qui soit. Es tu vraiment sûr d'en avoir besoin ?
    De plus, il est sûr que cette valeur dépend de l'instance de classe et tu parles d'une fonction static. C'est incohérent!

    Enfin, bonne chance

  15. #15
    Membre averti
    Inscrit en
    Mars 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 29
    Par défaut
    Effectivement tu as raison mais c'est indispensable pour l'utilisation de la technologie OleDB dansla réalisation d'un fournisseur OleDB.

    Merci encore Diogene pour ton aide

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

Discussions similaires

  1. [VB6] Exécuter une macro Access
    Par Nektanebos dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 22/02/2006, 16h32
  2. [VBA-E] Macro ouverture fichier déja ouvert
    Par bhaal76 dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 18/12/2002, 14h30
  3. [VBA-E] [Excel] Lancer une macro à une heure donnée
    Par Lysis dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 16/10/2002, 12h15
  4. Qu'est-ce qu'une macro ?
    Par karli dans le forum Assembleur
    Réponses: 2
    Dernier message: 01/09/2002, 03h38
  5. Réponses: 2
    Dernier message: 22/07/2002, 12h13

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