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 :

Allocation mémoire structure


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2012
    Messages : 83
    Par défaut Allocation mémoire structure
    Bonjour à tous !

    Suite à quelques tests concernant les structures, je sollicite votre aide afin d'y voir plus clair.
    Par 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
    typedef struct{
     
    int var1;
    int var2;
    int var3;
    } structure;
     
    structure test = {5,10,15};
     
    //Leurs adresses
    puts("Adresses");
    printf("\t%x\n",&test);
    printf("\t%x\n\n",&test.var1);
     
    //Leurs valeurs
    puts("Valeurs");
    printf("\t%x\n",test);
    printf("\t%x\n",test.var1);
    Résultat:

    Adresses
    ffbffa98
    ffbffa98

    Valeurs
    ffbffa88
    5

    Comment peuvent-elles avoir des valeurs différentes alors qu'elles ont la même adresse ?
    Est-ce parce que pour calculer la valeur de test le compilateur lit sur toute la taille de la structure ? Soit 3*(int) ?

    Merci de m'avoir lu !

  2. #2
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Bonsoir,

    je dois t'avouer que je n'ai jamais essayé de faire un printf d'une variable de type structure. Déjà en compilant avec gcc et -Wall -Wextra tu obtiens des warnings :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    > gcc -Wall -Wextra -g  -o test test.c 
    test.c: In function ‘main’:
    test.c:17:3: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘struct structure *’ [-Wformat]
    test.c:18:3: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int *’ [-Wformat]
    test.c:22:3: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘structure’ [-Wformat]
    qui te signalent que %x dans un printf s'attend à un unsigned int et que tu lui fournit tout autre chose. Pour imprimer la valeur des pointeurs tu devrais utiliser %p, c'est important car sur les systèmes où les pointeurs font 64bits et les int 32bits tu n'auras pas la bonne information d'imprimée.

    Maintenant la sortie que tu donnes m'interpelle un peu quand même ... tu travailles sur quelle plateforme ?

    Sinon je te propose le programme suivant pour test et explications :
    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
    #include <stdio.h>
     
    typedef struct{
     
      int var1;
      int var2;
      int var3;
    } structure;
     
     
    int main()
    {
      structure test = {5,10,15};
     
      //Leurs adresses                                                                                                                              
      puts("Adresses");
      printf("\t%p\n",&test);
      printf("\t%p\n\n",&test.var1);
     
      //Leurs valeurs                                                                                                                               
      puts("Valeurs");
      printf("\t%lX\n",test);
      printf("\t%X\n",test);
      printf("\t%X\n",test.var1);
     
      return 0;
    }
    On obtient toujours des warnings lors de la compilation. Mais passons. À l'exécution j'obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    > ./test 
    Adresses
    	0x7fff0ff69fe0
    	0x7fff0ff69fe0
     
    Valeurs
    	A00000005
    	5
    	5
    Que les adresses soient les même c'est normal, c'est imposé par la norme (l'adresse d'une variable de type structure est toujours l'adresse de son premier membre pour simplifier).
    Ensuite que se passe-t-il pour les printf des valeur ?
    Tu donnes dans le format du printf le type avec lequel sera interprété la valeur que tu passe en paramètre.
    Le premier printf affiche A00000005 en héxa, on lui passe la struct en paramètre et comme elle contient un entier 32bits valant 5 suivi d'un entier 32bits valant 10, l'interprétation de ce contenu mémoire comme un entier 64bits donne A00000005 (ce qui me semble cohérent avec mon OS, ici il n'y a pas de padding).
    Le second s'explique tout aussi simplement, on lui donne la structure qui contient 3 entiers 32bits et tu demandes de l'interpréter comme un entier 32bits, le cast donne le premier membre, ça ne me choque pas.
    Le troisième n'a pas besoin d'explications

    Tu comprends pourquoi ta sortie m'interpelle ... tu obtiens une adresse ... ça ne me semble pas cohérent en fait, mais ça ça doit dépendre du compilo et de la plateforme.

    Ce qui est important de retenir est qu'une struct n'a pas de valeur scalaire en soi et on ne doit pas considérer qu'elle en a une.
    Ce qu'on peut retenir est que print interprète ce que tu lui donne comme paramètres comme tu lui dis de le faire et que les warnings sont importants ...

  3. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2012
    Messages : 83
    Par défaut
    Merci pour votre réponse !

    J'utilise le compilateur gcc sur un serveur sous Unix (je n'en sais pas plus).

    Effectivement vos résultats sont nettement plus cohérents que les miens!

    Par contre:
    Le premier printf affiche A00000005 en héxa, on lui passe la struct en paramètre et comme elle contient un entier 32bits valant 5 suivi d'un entier 32bits valant 10, l'interprétation de ce contenu mémoire comme un entier 64bits donne A00000005 (ce qui me semble cohérent avec mon OS, ici il n'y a pas de padding).
    J'aurais crû que ça donnerait 50000000A. Comment se fait-il que la lecture s'effectue à l'envers ?

    (Veuillez excuser mon absence de réponse j'ai été vraiment très occupé avec la fin de l'année.)

  4. #4
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    C'est une question de boutisme (endianness).
    J'utilise linux sur un processeur x86 = sotckage petit-boutiste (little endian). Sur ma plateforme 64bits les int sont des entiers 32 bits (4 octets) et les long des entiers 64 bits (8 octets). test.var1 est un int qui vaut 5 donc en mémoire on a les quatre octets suivant qui sont stockés 0x05,0x00,0x00,0x00, ensuite test.var2 est aussi un int mais qui vaut 10, en mémoire on aura donc 0x0A,0x00,0x00,0x00.
    Passons maintenant au printf "%lX" sur test. test est une structure que l'on passe en paramètre, cette structure sera copiée et printf va considérer que le paramètre est un long (donc 64 bits/8 octets chez moi), il lit donc la mémoire où la copie est stockée sur 8 octets de long et interprète ça comme un long. Or à cet endroit il va trouver 0x05,0x00,0x00,0x00,0x0A,0x00,0x00,0x00 ce qui en little endian donne (on lit simplement à l'envers) 0x0000000A00000005, ce qui au final est affiché.

    Maintenant il y a aussi un «coup de bol» car pour d'autres raisons, test.var1 et test.var2 pourraient ne pas être contigus en mémoire (c'est ce qu'on appelle le padding).

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2012
    Messages : 83
    Par défaut
    Merci pour ces explications Kwariz!

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 07/10/2010, 20h16
  2. Pointeur, structure, allocation mémoire
    Par rirola12 dans le forum C
    Réponses: 4
    Dernier message: 22/04/2010, 17h14
  3. Allocation mémoire DCOM pour structure "complexe"
    Par squale32 dans le forum Windows
    Réponses: 14
    Dernier message: 01/07/2009, 17h48
  4. Réponses: 6
    Dernier message: 24/03/2006, 18h24
  5. Allocation mémoire dynamique
    Par ITISAR dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 21/01/2005, 09h59

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