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 :

Question sur les unions et leur zone mémoire.


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut Question sur les unions et leur zone mémoire.
    Bonjour, j'ai trouvé une question sur le web mais je ne saurais pas trop comment y répondre, je ne comprends pas la spécification comme quoi element reçu en paramètre ne doit pas partager la même zone mémoire que la nouvelle structure _fig

    Soient les déclarations suivantes:
    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
    struct _point {
    char x;
    char y;
    };
    typedef struct _point point;
    struct _rec {
    point bg;
    point hd;
    };
    struct _cer {
    point cen;
    unsigned char r;
    };
    struct _tri {
    point pa;
    point pb;
    point pc;
    };
    typedef struct _cer cercle;
    typedef struct _tri triangle;
    typedef struct _rec rectangle;
    enum type = {REC, CER, TRI};
    union _element {
    rectangle *rec;
    cercle *cer;
    triangle *tri;
    };
    typedef union _element ele;
    struct _fig {
    enum type typele;
    ele element;
    struct _fig *suivant;
    };
    typedef struct _fig fig;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fig * cons(ele element, enum type tf);
    La fonction cons permet de construire une structure de type fig selon le paramètre reçu element
    dont le type est donné par tf. La fonction cons retourne un pointeur sur la structure de type fig
    construite. Le champ suivant de cette structure sera mis à NULL. Votre code doit traiter toute les
    allocations dynamiques nécessaires pour que la structure construite ne partage aucune zone mémoire
    avec le paramètre reçu element. La fonction cons retourne NULL si tf ne correspond à aucune
    des valeurs définies dans enum type.


    si je fais fig = (fig*) malloc(sizeof(struct _fig));
    fig->typele = tf;
    fig->element = element;
    fiig->suivant = NULL;

    return fig;

    ça devrait être bon non ?

    J'ai de la difficulté à comprendre comment on peut initialiser un type union sans accéder a un de ses membre par un point.

    l'appele de la fonction se ferait comment ? Comme ceci ?

    ele unElement;
    unElement.cer = NULL;

    cons(unElement, CER);

    Je ne vois pas comment celui passé en paramètre puisse partager la même zone mémoire que dans la struct fig alloué dynamiquement, puisque c'est une copie.

    Merci pour votre aide.

  2. #2
    Membre expérimenté
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Points : 1 421
    Points
    1 421
    Par défaut
    j'ai du attendre la derniere phrase pour comprendre (et encore, je suis pas sur !) la question.

    pour que ta fonction utilise la meme variable (aka, la meme zone memoire) tu dois passer une copie de l'addresse de ta variable (par abus de langage, on dis passer une variable par reference ...) a ta fonction, au lieu d'une copie de ta variable.
    tu envoie l'addresse a ta fonction, et tu la recupere dans un pointeur.



    pour ton initialisation, tu peux utiliser memset vut que tu n'utilise que des chars (voir discussion sur memset dans ce meme forum pour plus de precisions)

    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
     
    fig * cons(ele *element, enum type tf)
    {
    fig *myfig=malloc(....)
    //some code ...
    return myfig;
    }
     
    int somefunction()
    {
    ele unElement;
    unElement.cer = NULL;
     
    cons(&unElement, CER);
    }
    ou alors ... j'ai rien compris a ta question.

    ha oui, dernier truc, le cast sur le retour du malloc, ça sert a rien.

  3. #3
    Membre averti
    Avatar de Foobar1329
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 283
    Points : 387
    Points
    387
    Par défaut
    Hello,

    Citation Envoyé par AsmCode
    Bonjour, j'ai trouvé une question sur le web mais je ne saurais pas trop comment y répondre, je ne comprends pas la spécification comme quoi element reçu en paramètre ne doit pas partager la même zone mémoire que la nouvelle structure _fig
    C'est simple, dans ton union element par exemple, tes membres partagent le même espace mémoire. Ce qui est demandé dans le cas présent, c'est de faire une recopie mémoire de ce qui est dans l'element dans la figure, donc ne pas faire une simple affectation de pointeur genre "figure->element.rec = elementEnParametre.rec", mais de faire une copie avec memcpy/memmove par exemple.

    <code strippé>

    Il ne faut pas utiliser d'underscores pour préfixer types, variables et autres en C, c'est réservé à l'implémentation.

    Citation Envoyé par AsmCode

    si je fais fig = (fig*) malloc(sizeof(struct _fig));
    fig->typele = tf;
    fig->element = element;
    fiig->suivant = NULL;

    return fig;

    ça devrait être bon non ?
    Non, car en faisant de la sorte (affectation element à fig->element), tu affectes aussi les (la en fait) valeurs de pointeurs et donc tu fait pointer par exemple fig->element.tri et element.tri sur le même emplacement en mémoire . Pas besoin de caster le retour de malloc().

    Citation Envoyé par AsmCode
    Je ne vois pas comment celui passé en paramètre puisse partager la même zone mémoire que dans la struct fig alloué dynamiquement, puisque c'est une copie.
    Oui, il s'agit d'une copie en ce qui concerne unElement. Mais comme les champs de l'union sont des pointeurs, tu peux faire de la recopie de pointeurs et donc utiliser le même espace mémoire pour tes figures.

    Voici un 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
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
     
     
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
     
    struct point {
       int x;
       int y;
    };
    typedef struct point point;
     
    struct rec {
       point bg;
       point hd;
    };
     
    struct cer {
       point cen;
       unsigned char r;
    };
     
    struct tri {
       point pa;
       point pb;
       point pc;
    };
     
    typedef struct cer cercle;
    typedef struct tri triangle;
    typedef struct rec rectangle;
     
    enum type {REC, CER, TRI};
     
    union element {
      rectangle * rec;
      cercle * cer;
      triangle * tri;
    };
     
    typedef union element ele;
     
    struct fig {
       enum type typele;
       ele element;
       struct fig * suivant;
    };
     
    typedef struct fig fig;
     
    fig * cons(ele element, enum type tf) {
     
        fig * figure = NULL;
        figure = malloc(sizeof(*figure));
     
        if (figure) {
     
          figure->suivant = NULL;
     
          if (element.rec) {
     
            size_t greaterSize = (sizeof(triangle) > sizeof(cercle) ) ? sizeof(triangle) : sizeof(cercle);
            greaterSize = (sizeof(rectangle) <  greaterSize) ? sizeof(rectangle) : greaterSize;
     
            figure->element.rec = malloc(sizeof(greaterSize)); 
            if (figure->element.rec) {
     
              memcpy(figure->element.rec, element.rec, greaterSize);
              if (tf == REC || tf == CER || tf == TRI) {
                figure->typele = tf;
              }
              else {
                free(figure), figure = NULL;
              }
            }
            else {
              free(figure), figure = NULL;
            }
          }
          else {
          free(figure), figure = NULL;
          }
     
     
        }
     
        return figure;
     
    }
     
    int main(void) {
     
      rectangle rect = { {0,1} , {2,4} }; 
     
      ele elRect;
      elRect.rec = &rect;
     
      fig * figure = cons(elRect, REC);
     
      if (figure) {
        printf("rec:(%d,%d) (%d,%d)\n", 
          figure->element.rec->bg.x,
          figure->element.rec->bg.y,
          figure->element.rec->hd.x,
          figure->element.rec->hd.y);
     
        free(figure), figure = NULL;
     
      }
     
      return 0;
     
    }
    A+

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut
    Mais je ne comprends pas pourquoi ça pointe sur la même zone de l'union si on ne fait pas memcopy ou memmove puisqu'on fait une copie de la mémoire lorsqu'on fait fig->element = element ça copy ce qu'il y a dans la zone mémoire de element passé en paramètre dans la zone mémoire de la nouvelle struct non ?

    En plus la zone mémoire passé en paramètre n'existe qu'a l'intérieur du scope de la fonction ?

    Mais en faisant fig->element = element ça copie toute la zone mémoire au lieu de si on fait fig->element.rec = element.rec de copier que la taille du pointeur ? quoi que ici tout les éléments du pointeurs sont des unions alors ça ne change rien je crois ..

  5. #5
    Membre averti
    Avatar de Foobar1329
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 283
    Points : 387
    Points
    387
    Par défaut
    Hello,

    Citation Envoyé par AsmCode
    Mais je ne comprends pas pourquoi ça pointe sur la même zone de l'union si on ne fait pas memcopy ou memmove puisqu'on fait une copie de la mémoire lorsqu'on fait fig->element = element ça copy ce qu'il y a dans la zone mémoire de element passé en paramètre dans la zone mémoire de la nouvelle struct non ?
    Pas du tout, cela fait pointer vers le même emplacement mémoire car c'est la valeur du pointeur qui est recopiée et non pas ce qui est pointé, d'où nécessité de recourir à memcpy()/memmove().

    Citation Envoyé par AsmCode
    En plus la zone mémoire passé en paramètre n'existe qu'a l'intérieur du scope de la fonction ?
    Un pointeur est une variable comme une autre, il s'agit d'une valeur numérique représentant une adresse. C'est l'adresse qui est recopiée, PAS la zone mémoire.

    Citation Envoyé par AsmCode
    Mais en faisant fig->element = element ça copie toute la zone mémoire au lieu de si on fait fig->element.rec = element.rec de copier que la taille du pointeur ? quoi que ici tout les éléments du pointeurs sont des unions alors ça ne change rien je crois ..
    fig->element = element et fig->element.rec = element.rec font à peu près la même chose (recopie d'adresse et non d'une zone mémoire) car element est une union.

    A+

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut
    Ok, mais element est un pointeur ? Je n'ai vu nulle part ou c'est déclaré comme un pointeur c'est pour cela que je ne comprends pas très bien.

    Dans ma tête c'est comme si je passais une variable, donc si je fais une nouvelle structure et que je copie la valeur de cette variable, la struct a une nouvelle zone mémoire donc la variable dans sa struct à aussi une nouvelle zone, donc le contenu est copié dans la nouvelle zone.

    Je ne vois pas pourquoi ce serait différent avec element.

    J'aurais peut-être besoin d'un dessin lol

  7. #7
    Membre expérimenté
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Points : 1 421
    Points
    1 421
    Par défaut
    Citation Envoyé par AsmCode
    Dans ma tête c'est comme si je passais une variable, donc si je fais une nouvelle structure et que je copie la valeur de cette variable, la struct a une nouvelle zone mémoire donc la variable dans sa struct à aussi une nouvelle zone, donc le contenu est copié dans la nouvelle zone.
    c'est exactement ce qu'il se passe, sauf que ta variable est un peu particuliere, c'est un pointeur
    un pointeur contiens l'addresse d'une zone memoire.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut
    Un pointeur ? Justement je ne vois pas ou c'est spécifié que c'est un pointeur, la valeur est un pointeur, mais la variable elle même non.

  9. #9
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 916
    Points
    17 916
    Billets dans le blog
    2
    Par défaut
    Quand tu fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    fig->element = element;
    tu ne copies pas le pointeur, mais les VALEURS .

    Donc quand tu fais return fig il bien évident que ça ne partage pas la même zone.

    Si tu voulais que cela la partage, il faudrait que dans fig, tu aies un POINTEUR pour element.

    Là, en faisant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    fig *fonction (ele *element )
    { 
    ...
    myfig->element = element;
    ...
     
    return myfig ;
    }
    tu affecterais au pointeur de type element de myfig la valeur du pointeur de type element passé en argument, et donc tu partagerais la même zone mémoire..

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut
    Ok, mais pourquoi alors dans la question il est demandé de faire toutes les allocation dynamique pour ne pas partager la même zone mémoire ? Une question piège ?

    Sinon la seule chose que je vois, étant donné que ce sont des pointeurs dans la variables, sans doute que cette zone mémoire pointé par le pointeur dans la variable qui ne doit pas partager la même zone mémoire ..

Discussions similaires

  1. Question métaphysique sur les unions
    Par lapique dans le forum C++
    Réponses: 7
    Dernier message: 29/05/2008, 18h12
  2. Réponses: 3
    Dernier message: 04/04/2008, 18h02
  3. Questions sur les shaders et leurs performances
    Par Dracul86 dans le forum Développement 2D, 3D et Jeux
    Réponses: 9
    Dernier message: 12/08/2007, 11h32
  4. Réponses: 7
    Dernier message: 17/02/2007, 09h22
  5. [C#] Questions sur les webmethodes et leur utilisation
    Par NoiBe dans le forum Services Web
    Réponses: 10
    Dernier message: 14/12/2006, 08h40

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