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 :

Questions sur la fonction get_binary, proposée dans les fichiers sources C


Sujet :

C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    10
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2006
    Messages : 10
    Points : 7
    Points
    7
    Par défaut Questions sur la fonction get_binary, proposée dans les fichiers sources C
    Bonjour,

    Je travaille actuellement sur un projet manipulant des données au niveau bit.

    J'ai trouvé la fonction get_binary sur votre site. Elle pourrait m'être utile pour tester les fonctions que je développe en controllant le motif binaire de mes sorties par rapport à celui de les entrées.

    Malheureusement, cette fonction a un comportement que je n'arrive pas à m'expliquer :
    • elle fonctionne parfaitement sur les unsigned int, unsigned long int et unsigned long long int mais,
    • elle echoue pour les unsigned char et les unsigned short int.


    Bien entendu, pour chaque nouveau type, je modifiais le code source. Voici, un exemble pour le motif binaire d'un unsigned short int :
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <limits.h>
     
     
    char * get_binary (unsigned short val, size_t * tab_size)
    {
       size_t size = sizeof (unsigned short) * CHAR_BIT;    /* Taille du type.      */
       size_t i = 0;
       char * tab = NULL;
     
     
       tab = malloc (size);
     
       if (tab != NULL)
       {
          for (i = 0; i < size; i++)
          {
             /*
              * On recupere les bits de la variable un par un en commencant
              * par les bits de poids faible (bits de droite) mais on les insere
              * dans le sens de lecture normal d'un etre humain soit de gauche
              * a droite.
              */
             tab[size - i - 1] = (val << (size - i - 1)) >> (size - 1);
          }
     
          if (tab_size != NULL)
          {
             *tab_size = size;
          }
       }
     
     
       return tab;
    }
     
     
    int main (void)
    {
       char * tab = NULL;
       size_t size = 0;
       size_t i = 0;
       unsigned short test = 90;
     
     
       tab = get_binary (test, & size);
     
       if (tab != NULL)
       {
          printf ("%d bits\n", size);
          for (i = 0; i < size; i++)
          {
             printf ("%d", tab[i]);
          }
          printf ("\n");
       }
     
       free (tab);
     
     
       return EXIT_SUCCESS;
    }
    L'auteur original de ces sources est Franck H. Je le remercie au passage pour ce petit programme pratique.

    Mes tentatives de debuggage m'ont permis de determiner que la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tab[size - i - 1] = (val << (size - i - 1)) >> (size - 1);
    était à l'origine des bugs.

    Quelqu'un aurait-il une explication ?


    Merci d'avance,


    Michaël

  2. #2
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Regardons comment le code fonctionne :

    Supposons, pour alléger l'écriture, que les unsigned int fassent 8 bits (size = 8) et que la valeur val soit en binaire 00001011
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
                                       i      0         1          2     ....
    (val << (size - i - 1))               10000000   11000000   01100000 
    (val << (size - i - 1)) >> (size - 1) 00000001   00000001   00000000
    Maintenant, la même chose avec un unsigned short qui, pour notre exemple, serait sur 4 bits size = 4 et val = 1011
    Dans cette expression, et c'est le problème, val est promu en unsigned int et val dans cette expression est une valeur sur 8 bits 00001011

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
                                       i      0         1          2     ....
    (val << (size - i - 1))               01011000   00101100   00010110 
    (val << (size - i - 1)) >> (size - 1) 00001011 ! 00000101 ! 00000010 !
    Il n'y a plus cet effet de "troncature" liée au nombre de bits. Dans ce cas, il faut le coder explicitement.

    Par exemple définir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       unsigned int mask = (unsigned short)(-1);
    et rajouter explicitement le masque
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       tab[size - i - 1] = ((val << (size - i - 1))& mask) >> (size - 1);
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    10
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2006
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    Merci beaucoup

    Il me reste deux petites questions cependant :

    Pourquoi val est-il promu en unsigned (long?) int dans l'expression ?
    Je suppose que c'est du à la variable size_t (équivalente a un long unsigned int).

    Je n'ai pas reussi à trouver la doc des opérateurs de décalage de bits >> et <<. J'ai cherché dans "Using the GNU Compiler Collection" et "The GNU C Library Reference Manual". Pourrais-tu m'aiguiller ?

    Désolé, je suis curieux

  4. #4
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Il faut chercher la documentation relative aux opérateurs >> et << dans une documentation sur le langage lui-même.
    Pour information, voila le paragraphe qui les concerne dans la norme (que tu peux consulter à partir de ce lien)
    (J'ai noté "a^^b" pour "a puissance b")
    6.5.7 Bitwise shift operators
    Syntax
    1 shift-expression:
    additive-expression
    shift-expression << additive-expression
    shift-expression >> additive-expression
    Constraints
    2 Each of the operands shall have integer type.
    Semantics
    3 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
    4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 x 2^^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 x 2^^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
    5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

    6.3.1.1 §2 explique la promotion des entiers. Pour résumer, elle concerne la conversion des "petits" entiers, c'est à dire des entiers qui sont d'un rang inférieur à int (donc char, short et leur version unsigned) en int (ou en unsigned int si la valeur ne peut être conservée dans cette transformation). Dans le cas qui nous occupe, si val est de type (unsigned)char ou (unsigned)short, il va être transformé en int.

    Ensuite, s'appliqueront les conversions habituelles décrites au paragraphe 6.3.1.8. val va être converti en le type size_t ou size dans le type de val (éventuellement non signé), cela dépend de la définition de size_t. Si size_t est un type unsigned d'un rang supérieur ou égal à celui de int (ce qui est probable), val va être converti en le type size_t. L'expression peut alors être évaluée.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  5. #5
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par roh01 Voir le message
    Je n'ai pas reussi à trouver la doc des opérateurs de décalage de bits >> et <<.
    http://emmanuel-delahaye.developpez....urs-bit-bit-c/
    Pas de Wi-Fi à la maison : CPL

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    10
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2006
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    Merci à vous deux.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 05/11/2011, 23h35
  2. Réponses: 3
    Dernier message: 30/05/2006, 17h28
  3. Réponses: 1
    Dernier message: 08/02/2006, 11h18
  4. Réponses: 2
    Dernier message: 21/12/2005, 09h39
  5. question sur le rafraichissement des données dans la base
    Par vbcasimir dans le forum Bases de données
    Réponses: 8
    Dernier message: 06/06/2005, 12h44

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