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 :

structures et unions ?


Sujet :

C

  1. #1
    Membre chevronné Avatar de jbarreau-mainson
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    446
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 446
    Par défaut structures et unions ?
    Bonjour à tous,

    Peut on eclairer ma lenterne sur les unions s'il vous plait ?!

    J'ai fait le tour des cours sur le site mais je suis un peu dans le flou.

  2. #2
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    T'es sûr d'avoir bien cherché ?

    Structures, unions et énumérations.

  3. #3
    Membre chevronné Avatar de jbarreau-mainson
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    446
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 446
    Par défaut
    Citation Envoyé par jbarreau-mainson
    J'ai fait le tour des cours sur le site mais je suis un peu dans le flou.
    Oui c'est le cours que j'avais vu.
    Mais je ne vois pas trop à quoi cela sert ou plutot comment s'en servir...

  4. #4
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Tu ne sais pas t'en servir ou tu ne vois pas leurs utilités ? Dans le premier cas je ne vois pas ce que je pourrai faire pour toi car il y a déjà des exemples dans le cours il me semble. Dans le deuxième cas, tu n'as juste pas encore assez d'expérience pour te rendre compte de leur utilité. Ne brusque pas les choses, ça viendra avec le temps. Ou bien j'ai encore mal compris la question ?

  5. #5
    Membre chevronné Avatar de jbarreau-mainson
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    446
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 446
    Par défaut
    Eh bien en fait je ne voit pas la difference avec une structure, mis à part le fait que les champs d'une union partagent le même espace mémoire.

    J'ai en fait un long qui a une valeur forcée, j'affiche la valeur de ce long à travers ce code :

    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
     
     
    typedef unsigned char uchar;
     
    int main()
    {
        long lg;
        lg = 0x12345678;
        uchar *pc;
     
        write(1,"lg = ", 5);
        for(pc = (uchar *)(&lg);pc < (uchar *)(&lg + 1); pc++)
        {
            printf("%.2X ", 0xFF&(*pc));
        }
    }
    Et j'aimerais à partir de là pouvoir déterminer msw, lsw, lsb et msb.
    On m'impose d'utiliser struct et union mais je bloque un peu ...

    Je pensais me diriger vers 3 struct :

    1 long lng; // Mot entier
    2 short shrt; // MSW & LSW
    1 char tab[3]; // Tab de 4 éléments : (lsb et msb)*2

    Je ne sais pas si c'est très clair

  6. #6
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Eh bien en fait je ne voit pas la difference avec une structure, mis à part le fait que les champs d'une union partagent le même espace mémoire.
    Bin volià la différence ! Dans une structure, les champs ne se chevauchent pas. Dans une union, on ne peut "activer" qu'un champ à chaque utilisation de l'union.

    Pour ce qu'on te demande de faire, c'est ta méthode qui est la bonne car portable (mais dans tous les cas on ne peut savoir si le premier octet est le msb ou le lsb qu'en sachant la plateforme sur laquelle on est. sur un processeur x86, premier octet en mémoire = lsb). Tu peux faire une version non portable en utilisant les unions avec la méthode que je vais te montrer un peu plus bas. L'idée c'est d'aller faire quelque chose comme ceci :
    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
    typedef struct bbbb_s {
        unsigned char b0;
        unsigned char b1;
        unsigned char b2;
        unsigned char b3;
    } BBBB;
     
    ...
     
    long lg = 0x12345678;
    BBBB b;
     
    // Sachant qu'un long fait 4 octets et un BBBB tout de même,
    // on peut copier tous les bits de lg vers b et lire facilement
    // le msb, le lsb, etc.
     
    memcpy(&b, &lg, 4);
     
    printf("lsb = %.2x\n", b.b0);
    printf("msb = %.2x\n", b.b3);
    L'utilisation d'une union permet de ne pas avoir à faire un memcpy.

    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
    #include <stdio.h>
     
    typedef struct bbbb_s {
        unsigned char b0;
        unsigned char b1;
        unsigned char b2;
        unsigned char b3;
    } BBBB;
     
    typedef struct ww_s {
        unsigned short w0;
        unsigned short w1;
    } WW;
     
    union lng
    {
        long lg;
        BBBB b;
        WW w;
    };
     
    int main()
    {
        union lng u;
     
        u.lg = 0x12345678;
     
        printf("lsb = %.2x\n", u.b.b0);
        printf("msb = %.2x\n", u.b.b3);
        printf("lsw = %.2x\n", u.w.w0);
        printf("msw = %.2x\n", u.w.w1);
     
        return 0;
    }

  7. #7
    Expert confirmé

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par jbarreau-mainson Voir le message
    Eh bien en fait je ne voit pas la difference avec une structure, mis à part le fait que les champs d'une union partagent le même espace mémoire.
    Pour la réponse à ton problème, voir plus haut.

    Pour l'utilité, en voici un mini-exemple..

    Soit une donnée que tu manipules, qui peut prendre n'importe quelle valeur int, long, float, double, char.

    Si tu veux faire un "objet" ayant cette valeur, et le manipuler de manière "transparente", tu as 2 choix..

    Structure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    typedef struct _pValue {
     
        int    i ;
        long   l ;
        float  f ;
        double d ;
        char   c ;
     
    } Value ;
    Union :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    typedef union _pValue {
     
        int    i ;
        long   l ;
        float  f ;
        double d ;
        char   c ;
     
    } Value ;

    Dans le premier cas, la taille sera la somme des tailles (au moins), dans le second la plus grande (sizeof(double) ).

    Si donc tu n'as pas besoin d'optimisation, ou que ta "modélisation" est peu importante, la structure marche bien.

    Si par contre tu as (auras) beaucoup d'objets en mémoire, et/ou que ta "modélisation" (objet) est importante, tu prendras l'union, qui demande beaucoup moins de mémoire et qui est plus "object-like"...


  8. #8
    Membre chevronné Avatar de jbarreau-mainson
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    446
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 446
    Par défaut
    C'est beaucoup plus clair maintenant, merci à vous !

  9. #9
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 160
    Billets dans le blog
    152
    Par défaut
    @souviron34 : Je ne comprend pas en quoi ton exemple serai utile ...
    Car certe l'union gagne de la place , mais du coup la multitude de types que t'utilise son la même chose, donc si tu en modifie tu les modifie tous. Donc si tu as besoin de plus de variables aux même instants , tu aura besoin de refaire des variables de ton union. Ou alors c'est dans un cas ( que je trouve dangereux ) ou tu réutilise la meme variable après utilisation... donc avec un autre type comme te le permet l'union ...

    ( Je trouve ça dangereux, car cela peut être source de bug , si on est pas rigoureux )
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  10. #10
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Ou alors c'est dans un cas ( que je trouve dangereux ) ou tu réutilise la meme variable après utilisation... donc avec un autre type comme te le permet l'union ...

    ( Je trouve ça dangereux, car cela peut être source de bug , si on est pas rigoureux )
    Il faut certes être prudent, mais l'usage d'une union pour gagner de la place et donc de "recycler" une ancienne variable en en changeant le type est une pratique assez fréquente (bien qu'en perte de vitesse car de moins en moins nécessaire avec l'augmentation de la mémoire disponible même dans les environnement limité) et c'est à peu près le seul cas où l'utilisation de l'union est portable.

  11. #11
    Expert confirmé

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    @souviron34 : Je ne comprend pas en quoi ton exemple serai utile ...
    Car certe l'union gagne de la place , mais du coup la multitude de types que t'utilise son la même chose, donc si tu en modifie tu les modifie tous. Donc si tu as besoin de plus de variables aux même instants , tu aura besoin de refaire des variables de ton union. Ou alors c'est dans un cas ( que je trouve dangereux ) ou tu réutilise la meme variable après utilisation... donc avec un autre type comme te le permet l'union ...

    ( Je trouve ça dangereux, car cela peut être source de bug , si on est pas rigoureux )
    Voir plus bas, mais ton "premier cas" est impossible : tu ne fais une union que de choses logiques qui ne bougent pas dans le temps (voir exemple ci-dessous).

    Dans ton "second cas", c'est pareil. Ce cas est rare, mais l'utilisation la plus fréquente est ci-dessous...

    Citation Envoyé par gl Voir le message
    Il faut certes être prudent, mais l'usage d'une union pour gagner de la place et donc de "recycler" une ancienne variable en en changeant le type est une pratique assez fréquente (bien qu'en perte de vitesse car de moins en moins nécessaire avec l'augmentation de la mémoire disponible même dans les environnement limité) et c'est à peu près le seul cas où l'utilisation de l'union est portable.
    C'est au contraire très courant dans les softs industriels,pour une raison simple :

    comme dit plus haut, cela correspond à une programmation "orientée objet".

    Si tu as par exemple un serveur envoyant des données (je l'ai eu pour la météo par exemple). Ces données sont par exemple la température (nombre réel : degrés), la précipitation (nombre entier : mm), le nom de la station de mesure (chaine de caractères), la photo de ce qui se passe à l'extérieur de la station (buffer de unsigned char : image), etc etc... tu as une routine Receive_Data. Cette fonction va décoder la réponse et stocker dans des buffers les données, qui sont de types différents. Sauf qu'après, dans tout le soft, la valeur de la donnée n'est qu'un des multiples éléments de la donnée (date d'émission, date de réception, posiition géographique, etc etc).

    Donc tu fais une union, car ce n'est pas le même endroit "recyclé", comme dit plus haut, mais différentes manières d'accéder à la valeur pour des types différents...

    Admettons que tu aies 450 000 points. Au lieu d'avoir 450 000 fois (4+4+8+8+1) octets tu auras 450 000 * 8, soit un gain absolument non négligeable en mémoire (66% de gain), et de plus beaucoup plus transparent :

    Tu auras par exemple des fonctions style Affiche_Data, Trace_Data, etc etc, et ce ne sera qu'au niveau le plus profond que tu décideras en fonction du type qu'est-ce que tu choisis.

    @gl :

    • primo il faut toujours tenter de faire un programme qui consomme le moins possible : tu ne peux pas imposer à un client (même si c'est ce que fait M$) d'augmenter indéféniment sa mémoire), et d'autre part tu ne peux pas forcément savoir de combien tu disposeras (mes programmes tournent sans rien changer de 2 Megs à 500 Gigs de mémoire).
    • secondo le problème n'est pas de recycler mais de programmer de manière "objet" et cohérente... Je ne comprend donc pas ce que tu dis que c'est de moins en moins utilisé... C'est au contraire dans le droit-fil de la POO. C'est beaucoup plus compliqué de faire rentrer un schéma de structure dans un schéma OO que de dire que la valeur est soit un entier, soit un réel, soit .., car cela devient une "contrainte d'implémentation" ou de langage, et non une modélisation.

  12. #12
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    Citation Envoyé par gl Voir le message
    Il faut certes être prudent, mais l'usage d'une union pour gagner de la place et donc de "recycler" une ancienne variable en en changeant le type est une pratique assez fréquente (bien qu'en perte de vitesse car de moins en moins nécessaire avec l'augmentation de la mémoire disponible même dans les environnement limité) et c'est à peu près le seul cas où l'utilisation de l'union est portable.
    C'est au contraire très courant dans les softs industriels,pour une raison simple :

    comme dit plus haut, cela correspond à une programmation "orientée objet".
    Oui et ? Où est-ce que j'ai prétendu le contraire ?
    Je répondais à la remarque de LittleWhite concernant la réutilisation de mémoire grâce à une union, qui est bel et bien une pratique en voie de disparation (et je serais tenter de dire heureusement).
    Je ne prétends pas que les autres utilisations de l'union était de moins en moins utilisé. Si mon message précédent est ambigu, je m'en excuse.

    Ceci étant l'utilisation des union pour programmer "orienté objet" n'est qu'une des façons de faire et ce n'est pas celle que j'ai rencontrée ou utilisée le plus fréquemment (généralement c'est plutôt à base de void* + taille du type). Mais il est fort possible que dans d'autres domaines que le mien, l'utilisation d'union dans le but de faire de la POO soit plus fréquent.

    Citation Envoyé par souviron34 Voir le message
    Si tu as par exemple un serveur envoyant des données (je l'ai eu pour la météo par exemple). Ces données sont par exemple la température (nombre réel : degrés), la précipitation (nombre entier : mm), le nom de la station de mesure (chaine de caractères), la photo de ce qui se passe à l'extérieur de la station (buffer de unsigned char : image), etc etc... tu as une routine Receive_Data. Cette fonction va décoder la réponse et stocker dans des buffers les données, qui sont de types différents. Sauf qu'après, dans tout le soft, la valeur de la donnée n'est qu'un des multiples éléments de la donnée (date d'émission, date de réception, posiition géographique, etc etc).
    Par contre je n'ai pas compris dans ton exemple où tu faisais intervenir l'union. Lors de la réception (ie dans Receive_Data) ou ensuite pour traiter les données ?

    Citation Envoyé par souviron34 Voir le message
    Donc tu fais une union, car ce n'est pas le même endroit "recyclé", comme dit plus haut, mais différentes manières d'accéder à la valeur pour des types différents...
    Je ne suis pas sur de bien comprendre ce que tu cherches à dire par là.
    Tu ne cherches tout de même pas à traiter une même valeur comme étant de différents types selon le contexte ?


    Citation Envoyé par souviron34 Voir le message
    primo il faut toujours tenter de faire un programme qui consomme le moins possible : tu ne peux pas imposer à un client (même si c'est ce que fait M$) d'augmenter indéféniment sa mémoire), et d'autre part tu ne peux pas forcément savoir de combien tu disposeras (mes programmes tournent sans rien changer de 2 Megs à 500 Gigs de mémoire).
    Je suis entièrement d'accord qu'il ne faille pas gaspiller des ressources (mémoire ou autre). cependant, cette économie de mémoire ne doit pas être fait au détriment de la maintenabilité, de l'évolubilité, de la robustesse ou de la souplesse du programme comme cela a pu être fait lorsque la mémoire était une ressource vraiment rare.
    En outre supposer que le programme devra tourner sur du matériel correspondant à la réalité du moment ce n'est pas tout à fait la même chose que "augmenter indéfiniment la mémoire disponible".

    Citation Envoyé par souviron34 Voir le message
    secondo le problème n'est pas de recycler mais de programmer de manière "objet" et cohérente... Je ne comprend donc pas ce que tu dis que c'est de moins en moins utilisé... C'est au contraire dans le droit-fil de la POO. C'est beaucoup plus compliqué de faire rentrer un schéma de structure dans un schéma OO que de dire que la valeur est soit un entier, soit un réel, soit .., car cela devient une "contrainte d'implémentation" ou de langage, et non une modélisation.
    Comme indiqué précédemment, je répondais uniquement à l'interrogation de LittleWhite concernant la réutilisation de mémoire pour gagner de la place, pas à autre chose. Je ne vois pas où, dans mon message, j'ai parlé d'OO et donc ce qui te permet de tirer cette conclusion de mes propos.
    Merci de ne pas me prêter des intentions qui ne sont pas les miennes, qui plus est sur des sujets qui ne sont pas aborder dans mes messages.

  13. #13
    Expert confirmé

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    désolé si je me suis mal exprimé mon but n'était pas de te contredire mais d'ajouter à la discussion .. désolé..

    Pour, l'OO, c'est moi qui en parlait pour expliciter mon propos pour LittleWhite.

    Pour l'exemple, c'est dans le Receive_Data et ailleurs, juste pour stocker les valeurs.... dans les buffers, avec le type correct.

    Je n'avais pas compris ta remarque vis-à-vis de la ré-utilisation...

    tot va ben

  14. #14
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    désolé si je me suis mal exprimé mon but n'était pas de te contredire mais d'ajouter à la discussion .. désolé..

    Pour, l'OO, c'est moi qui en parlait pour expliciter mon propos pour LittleWhite.

    Pour l'exemple, c'est dans le Receive_Data et ailleurs, juste pour stocker les valeurs.... dans les buffers, avec le type correct.

    Je n'avais pas compris ta remarque vis-à-vis de la ré-utilisation...

    tot va ben
    Il n'y a pas de mal.

    Juste une petite remarque au niveau terminologie : dans le cas de l'utilisation de l'union comme tu le fais, je parlerais de généricité plutôt que de POO.
    En effet, même si couplé à d'autre mécanisme l'utilisation de l'union permet de faire de la POO en C, ce mécanisme (et donc cette généricité) peut être employée hors du cadre de la POO tout comme il peut être possible d'avoir une forme minimale de POO sans cette généricité.

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

Discussions similaires

  1. Structure et Union
    Par Ryu2000 dans le forum Débuter
    Réponses: 2
    Dernier message: 12/02/2013, 11h27
  2. Structure et unions en C
    Par isildur37 dans le forum Débuter
    Réponses: 2
    Dernier message: 22/12/2009, 15h16
  3. structure, union et énumération
    Par ngalla dans le forum C
    Réponses: 3
    Dernier message: 14/03/2007, 10h34
  4. Structure, union et pointeur
    Par kikoo.plop dans le forum C
    Réponses: 10
    Dernier message: 18/12/2006, 19h21
  5. union de structure syntaxe
    Par al974 dans le forum C
    Réponses: 6
    Dernier message: 29/07/2006, 13h56

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