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 :

manipulation de champs de bits


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 249
    Par défaut manipulation de champs de bits
    Bonjour,

    Je programme sur un microcontrolleur 8 bit (PIC18 de chez microchip) et j'utilise le compilateur MCC18 (microchip).

    J'ai défini des unions et des structures :
    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
    typedef struct _Struct1 {
    	unsigned int a;
    	unsigned char b;
    } Struct1;
     
     
    typedef union _Union2 {
    	unsigned int Val;
     
        struct
        {
            unsigned char ValL;
            unsigned char ValH;
        };
     
    	struct {
    		unsigned int a:8;	// bit0-7
     
    		unsigned int b:8;			// bit8-15
    	};
    } Union2;
    Union2 myVar2;
     
     
    typedef union _Union3 {
    	unsigned int Val;
     
        struct
        {
            unsigned char ValL;
            unsigned char ValH;
        };
     
    	struct {
    		unsigned int a:1;	// bit0
    		unsigned int b:1;	// bit1
    		unsigned int c:1;	// bit2
    		unsigned int d:1;	// bit3
    		unsigned int e:1;	// bit4
    		unsigned int f:1;	// bit5
    		unsigned int g:1;	// bit6
    		unsigned int h:1;	// bit7
     
    		unsigned int i:2;	// bit8-9
    		unsigned int j:4;	// bit10-13
    		unsigned int k:1;	// bit14
    		unsigned int l:1;	// bit15
    	};
    } Union3;
    Union3 myVar3;
    et voici mon programme (myVar2 et myVar3 sont des variables globales) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Struct1 myVar1;
    myVar1.a = (myVar2.a << 4);
    myVar1.a |= myVar3.j;
    => ça ne fonctionne pas correctement, la valeur de myVar1.a n'est pas correcte : j'ai l'impression que j'ai des problème sur les opérations de décalage (ça décale sur toute la variable au lieu du champs. Est-ce que je peux avoir le même problème sur des opérations logique tel que OU, ET, NON ... ?)

    par contre ce code "à l'air de fonctionner" correctement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Struct1 myVar1;
    myVar1.a = ((unsigned int)myVar2.a << 4);
    myVar1.a |= myVar3.j;

    => pouvez-vous me dire de quoi ça vient ? ... a priori l'utilisation de champs de bits pose des problèmes si on fait des opérations tel que des décalages.
    Quels sont les méthodes à utiliser pour faire des décalages et des opération logique sur des champs de bits sans avoir de mauvaises surprises ?

  2. #2
    Membre confirmé
    Inscrit en
    Mars 2006
    Messages
    117
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Mars 2006
    Messages : 117
    Par défaut
    normalement quand tu fais des champs de bits tu specifie au compilateur que tu ne veux utiliser q'un seul bits sur la totalité du type de base que tu as choisis. Mais rien ne lui dis de ne pas laisser quand meme ces bits inutilisées. Du coup quand tu fais un decalage tes bits partent dans les bits restant non utilisées.

    essaye de declarer tes structures etc avec __attribute__((__packed__));

    tu peux trouver un petit exemple ici : grok2.tripod.com/structure_packing.html

    par contre je sais que cela fonctionne avec gcc, mais je ne connais pas ton compilateur. Donc rien ne dis que cela existe, mais à mon avis le probleme general vient de cette idée de bits utilisées et de bits non utilisées mais quand meme presents.

    ce n'est qu'une idée, je ne garantie pas que ce soit la reponse.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 249
    Par défaut
    désolé mais je n'ai pas bien compris ton explication...

  4. #4
    Membre confirmé
    Inscrit en
    Mars 2006
    Messages
    117
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Mars 2006
    Messages : 117
    Par défaut
    considerons pour l'exemple que nous sommes sur une archi classique avec 1 octets pour un char soit 1* 8 = 8bits
    lorsque tu fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    unsigned char a:4;
    tu specifies au compilateur que tu souhaites utilisées un char, mais uniquement les 4 1er bit et d'ignorer les autres. Mais ca n'empeche que les 4bits restant ont bien été reservé et sont present.
    Du coup si tu fais un decalage de bit imaginons de 2 avec ton char ayant la forme suivante en memoire :
    0000 1010 << 2
    = 0010 1000 (decalage sur tout le type) et non pas comme tu le souhaiterai : 0000 1000 (decalage uniquement sur les bits qui t'interesse).

    du coup si apres tu fais une affection vers un char normal, et que tu les affiches, ils n'auront pas le meme caractere l'un affichera le caractere 40 (00101000) l'autre le caractere 8 (1000).

    Il en va de meme pour les int (j'ai pris des char car moins de bits pour l'exemple ! ) lors de ton affectation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    myVar1.a = (myVar2.a << 4);
    myvar1.a est de type int "normal" donc sur 4 octets (en archi classique) alors que ton myvar2.a lui est sur 8.

    j'espere avoir été plus clair, une fois de plus je me repete ce n'est qu'une piste à laquel j'ai pensé en lisant ton code.

    le attributs packed te permet de specifier (à gcc en tout cas) de supprimer ces bits "inutilisées".

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 249
    Par défaut
    j'ai fait quelques tests et a priori ça ne vient pas de ça. Voici des résultats de calculs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    si myVar2.a = 0x00 et myVar3.j = 0xF, myVar1.a = 0x000F (c'est bon)
    si myVar2.a = 0x0F et myVar3.j = 0xF, myVar1.a = 0x00FF (c'est bon)
     
    si myVar2.a = 0x10 et myVar3.j = 0x0, myVar1.a = 0x0000 (on devrait avoir  0x0100)
    si myVar2.a = 0x10 et myVar3.j = 0x1, myVar1.a = 0x0001 (on devrait avoir 0x0101)
     
    si myVar2.a = 0x20 et myVar3.j = 0x0, myVar1.a = 0x0000 (on devrait avoir 0x0200)
    si myVar2.a = 0x20 et myVar3.j = 0x1, myVar1.a = 0x0001 (on devrait avoir 0x0201) 
    si myVar2.a = 0x1e et myVar3.j = 0xe, myVar1.a = 0x00ee (on devrait avoir 0x01ee)
    => donc a priori, le deuxième quartet de myVar2.a est tronqué


    donc la commande :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    myVar1.a = (myVar2.a << 4);
    doit être équivalente à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    unsigned char myVal;
    myVal = myVar2.a;
    myVal <<= 4;
    myVar1.a = myVal;
    => mais je ne sais pas trop le pourquoi du comment ...

  6. #6
    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
    myVar2.a; (où le champ a est un champ de bits unsigned int a : 8; ) est évalué comme un unsigned int dont la valeur est celle obtenue par les 8 bits du champ de bits. Ce n'est pas du tout une valeur qui aurait 8 bits.
    le type associé au champ de bits indique en fait le type de la valeur qu'on souhaite utiliser pour lire ce champ de bits.

    Lors de la réécriture dans le champ de bits, la valeur est tronquée à la taille du champ de bits :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    myVar1.a = (myVar2.a << 4);
    // myVar2.a  : valeur 0x10 type unsigned int 
    // (myVar2.a << 4) : valeur 0x100 type unsigned int 
    // myVar1.a = (myVar2.a << 4) : le champ 'a' prend la valeur 0x00 (8 derniers bits de la valeur 0x100)

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 249
    Par défaut
    ok merci pour l'info

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

Discussions similaires

  1. Manipulation de champs de table
    Par beberd dans le forum SQL Procédural
    Réponses: 1
    Dernier message: 27/12/2006, 13h05
  2. enum et champs de bits
    Par FamiDoo dans le forum C++
    Réponses: 12
    Dernier message: 12/07/2006, 13h22
  3. Champs de bit et affectation
    Par the_ionic dans le forum C
    Réponses: 11
    Dernier message: 09/06/2006, 16h13
  4. [Dates] manipulation de champ date
    Par PAYASS59 dans le forum Langage
    Réponses: 9
    Dernier message: 23/02/2006, 11h13
  5. lire un champ de bit a partir d'un fichier
    Par loupdeau dans le forum MFC
    Réponses: 5
    Dernier message: 09/08/2005, 12h53

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