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 métaphysique sur les unions


Sujet :

C++

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Février 2006
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 3
    Points : 1
    Points
    1
    Par défaut Question métaphysique sur les unions
    Dans l'union U2, len est déclaré en short au lieu de char, et du coup, "char command" est codé sur 2 octets. Mais pourquoi ???

    Merci de votre aide.


    Plateforme : WinXP, mingw32, g++

    Compilation :
    g++ -Wall -gstabs -o union.exe union.cpp && union


    -----------------------------------------
    Sortie du programme :
    Union 1 :
    01 02 00 01

    Union 2 :
    01 00 02 00 00 01

    -----------------------------------------

    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
     
     
    #include <iostream>
    #include <iomanip>
     
    using namespace std;
     
    /*
    len : nbre d'octets dans data
    */
     
    typedef union U1
    {
    	char _bytes[512];											// 512 octets
     
    	struct
    	{
    		char command;							// 1 octet
    		char len;							// 1 octet
    		char data[512-sizeof(char)-sizeof(char)];		// 510 octets
    	} dPkt;
     
    } T1;
     
     
    typedef union U2
    {
    	char _bytes[512];						// 512 octets
     
    	struct
    	{
    		char command;						// normalement 1 octet
    		short len;						    // 2 octet
    		char data[512-sizeof(char)-sizeof(short)];	// 509 octets
    	} dPkt;
     
    } T2;
     
     
     
     
    void affiche(const char *s,size_t n);
     
    int main()
    {
    	short value=256;	// 256 = 0x0100 ; codage little-endian : 00 01
     
    	T1 v1;
    	v1.dPkt.command=1;
    	v1.dPkt.len=2;
    	memcpy(v1.dPkt.data,&value,sizeof(short));
    	cout<<"Union 1 :\n";
    	affiche(v1._bytes,4);	// 1 (command) + 1 (len) + 2 (value) = 4
     
    	T2 v2;
    	v2.dPkt.command=1;
    	v2.dPkt.len=2;
    	memcpy(v2.dPkt.data,&value,sizeof(short));
    	cout<<"\nUnion 2 :\n";
    	affiche(v2._bytes,6);	// 2 et pas 1! (command) + 2 (len) + 2 (value) = 6
     
    	return 0;
    }
     
     
     
    void affiche(const char *s,size_t n)
    {
    	for(size_t i=0;i<n;i++)
    		cout<<setfill('0')<<hex<<setw(2)<<(short)s[i]<<' ';
    	cout<<endl;
    }

  2. #2
    jmv
    jmv est déconnecté
    Membre confirmé Avatar de jmv
    Profil pro
    Enseignant
    Inscrit en
    Mai 2004
    Messages
    395
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Mai 2004
    Messages : 395
    Points : 603
    Points
    603
    Par défaut
    salut,

    il s'agit probablement d'un alignement sur des mots de 16 bits.
    je ne connais pas tres bien g++ mais regarde s'il n'y a pas une option qui permet de regler cet alignement.

    a+
    jmv

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    126
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 126
    Points : 149
    Points
    149
    Par défaut Taille union


    Le stockage alloué pour une union est égal au stockage requis pour le plus grand membre de cette union (en C++ en tout cas). Donc pour chaque donnée, la taille associée ne correspond pas au type de la donnée mais à celle de la donnée la plus grande de l'union (ici le short sur 2 bytes).

    A+,

  4. #4
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Février 2006
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    D'accord, mais dans ce cas, les 2 membres de l'union sont :
    - char _bytes[512]
    - struct { ... } dPkt

    Donc je m'attends à ce que le coup des longueurs de stockage s'applique à ces 2 membres, et pas aux membres dans la structure. Mais c'est peut-être pas ça.

    D'autre part, je voudrais éviter d'avoir à jouer sur les réglages du compilateur pour avoir un code aussi portable que possible.

  5. #5
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Dans l'union U2, len est déclaré en short au lieu de char, et du coup, "char command" est codé sur 2 octets. Mais pourquoi ???
    Parce qu'un short doit être aligné sur 2 octets.
    Le problème se résout en mettant le membre len en premier. Ou en donnant comme type à len char[2].

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    Déjà, sizeof(char) est sans doute la seule valeur dont on peut être sûr au niveau des tailles des types primitifs: ca vaut 1

    tu pourrais donc déjà tout à fait simplifier les codes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char data[512-sizeof(char)-sizeof(char)];
    en
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char data[512-sizeof(char)-sizeof(short)];
    en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char data[511-sizeof(short)];

    Ceci étant dit:

    Effectivement, dPkt utilise la même mémoire que _bytes, et donc a une taille de ... 512 octets.
    Parmis ces 512 octets, il y en a 1 pour command, 1 (ou deux) pour len, et le reste pour data, ce qui est logique

    Par contre, il faut savoir que, len signifie "taille" en anglais et que, *typiquement", sur PC:
    • un type char permet de représenter 256 valeurs (de 0 à 255)
    • un type short permet de représenter 65536 valeurs (de 0 à 65535)

    Il en résulte que, dans U1, la taille maximale que len peut représenter (*typiquement* 255) est inférieure au nombre d'octet que peut prendre data (510), et que tu perd donc tout le bénéfice que tu peux trouver à travailler sur... 512 octets pour ta structure.

    Avec U2, cependant, il n'y a plus ce problème:

    len peut représenter 65536 valeurs, et est donc tout à fait capable de représenter toutes les tailles possibles pour data (qui ne fait "que" 509 octets, si l'on considère qu'un short = 2 char )

    La seule chose à laquelle faudra être attentif pour la cohérence des données, c'est que, en tout état de cause, len ne vaille jamais plus que... 509 (qui est le nombre maximal d'octets que peut contenir data)

    Enfin, si le but est de créer quelque chose qui soit le plus portable possible, les deux conseils à donner sont:
    • De ne pas utiliser d'union
    • d'utiliser de préférence les types dont la taille est clairement définie (uint8_t, uint16_t et autres similaires)

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

    Informations forums :
    Inscription : Février 2006
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Effectivement, ne pas utiliser d'union, supprime les problèmes avec les unions, c'est radical. Merci du conseil ! Mais je reste sur ma faim...

  8. #8
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Je t'ai proposé deux solutions.

Discussions similaires

  1. Réponses: 9
    Dernier message: 17/03/2007, 05h49
  2. [Struts] question bete sur les Action et Form
    Par seb_fou dans le forum Struts 1
    Réponses: 2
    Dernier message: 06/09/2004, 15h24
  3. question générale sur les conteneurs
    Par tut dans le forum C++
    Réponses: 6
    Dernier message: 01/09/2004, 10h11
  4. Question générale sur les affectations ?
    Par Clemaster dans le forum C++
    Réponses: 5
    Dernier message: 09/08/2004, 17h03
  5. Question simple sur les threads :)
    Par momox dans le forum C++Builder
    Réponses: 2
    Dernier message: 15/06/2003, 04h13

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