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 :

opérateur de bits sur type signé


Sujet :

C

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    mars 2006
    Messages
    277
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2006
    Messages : 277
    Points : 141
    Points
    141
    Par défaut opérateur de bits sur type signé
    Bonjour,

    Je suis en train de passer un outil sur des sources en C.
    Une opération de bits (>>, <<, &, |, ~...) sur un nombre signé provoque une erreur. J'aimerais supprimer cette erreur.
    J'ai dans l'idée de récupérer les bits de la variable signée pour les assigner à une variable non signée et ensuite faire mes comparaison de bits, comment faut-il que je fasse ?

    J'ai fait un petit programme, qui me permet de faire des essais sur des nombre signés et l'utilisation de cast, mais je ne sais pas si un cast est suffisant pour tous les cas :
    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
    /* Dans ce programme il y a de la manipulation de fichiers */
    /* Pour compiler faire "gcc -o test test.c" */
    /* Pour executer faire "exec test &" */
     
    #include <stdio.h>
    #include <string.h>
     
     
    int main (void)
    {
        char var_int ;
        unsigned char var_uint ;
        char result, result2 ;
     
        var_int = -8 ;
        var_uint = 8 ;
        printf("valeurs de base var_int:%d, var_uint:%d\n", var_int, var_uint) ;
     
    	result = ((var_int >> 4) & 0x0F) | 0x30; /* LINT_NON_INTEGER */
    	result2 = ((var_int << 4)& 0xF0); /* LINT_NON_INTEGER */
        printf("resultats : result:%d, result2:%d\n", result, result2) ;
     
    	result = ((var_uint >> 4) & 0x0F) | 0x30; /* LINT_NON_INTEGER */
    	result2 = ((var_uint << 4)& 0xF0); /* LINT_NON_INTEGER */
        printf("resultats : result:%d, result2:%d\n", result, result2) ;
     
        var_int = 0xf0 ;
        var_uint = 0xf0 ;
        printf("valeurs de base var_int:%d, var_uint:%d\n", var_int, var_uint) ;
     
    	result = ((var_int >> 4) & 0x0F) | 0x30; /* LINT_NON_INTEGER */
    	result2 = ((var_int << 4)& 0xF0); /* LINT_NON_INTEGER */
        printf("resultats : result:%d, result2:%d\n", result, result2) ;
     
    	result = ((var_uint >> 4) & 0x0F) | 0x30; /* LINT_NON_INTEGER */
    	result2 = ((var_uint << 4)& 0xF0); /* LINT_NON_INTEGER */
        printf("resultats : result:%d, result2:%d\n", result, result2) ;
     
        var_int = -8 ;
        var_uint = 8 ;
        printf("valeurs de base var_int:%d, var_uint:%d\n", ((unsigned char)var_int), var_uint) ;
     
    	result = ((((unsigned char)var_int) >> 4) & 0x0F) | 0x30; /* LINT_NON_INTEGER */
    	result2 = ((((unsigned char)var_int) << 4)& 0xF0); /* LINT_NON_INTEGER */
        printf("resultats : result:%d, result2:%d\n", result, result2) ;
     
    	result = ((var_uint >> 4) & 0x0F) | 0x30; /* LINT_NON_INTEGER */
    	result2 = ((var_uint << 4)& 0xF0); /* LINT_NON_INTEGER */
        printf("resultats : result:%d, result2:%d\n", result, result2) ;
     
        var_int = 0xf0 ;
        var_uint = 0xf0 ;
        printf("valeurs de base var_int:%d, var_uint:%d\n", ((unsigned char)var_int), var_uint) ;
     
    	result = ((((unsigned char)var_int) >> 4) & 0x0F) | 0x30; /* LINT_NON_INTEGER */
    	result2 = ((((unsigned char)var_int) << 4)& 0xF0); /* LINT_NON_INTEGER */
        printf("resultats : result:%d, result2:%d\n", result, result2) ;
     
    	result = ((var_uint >> 4) & 0x0F) | 0x30; /* LINT_NON_INTEGER */
    	result2 = ((var_uint << 4)& 0xF0); /* LINT_NON_INTEGER */
        printf("resultats : result:%d, result2:%d\n", result, result2) ;
     
    	return (0) ;
    }
    Voici les résultats :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    valeurs de base var_int:-8, var_uint:8
    resultats : result:63, result2:-128
    resultats : result:48, result2:-128
    valeurs de base var_int:-16, var_uint:240
    resultats : result:63, result2:0
    resultats : result:63, result2:0
    valeurs de base var_int:-8, var_uint:248
    resultats : result:63, result2:-128
    resultats : result:63, result2:-128
    valeurs de base var_int:240, var_uint:240
    resultats : result:63, result2:0
    resultats : result:63, result2:0
    dites moi si c'est une bonne méthode pour supprimer les erreurs

  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 727
    Points
    13 727
    Par défaut
    Il faut distinguer 2 cas : celui des opérateurs de décalage (>> et <<) et les opérateurs de manipulation de bits (&, |,...)

    - Dans le premier cas, le comportement est partiellement défini de façon abstraite donc indépendamment de la représentation des entiers : Il suffit que le nombre soit non signé ou signé mais positif et que le résultat soit représentable dans le type de donnée du résultat. Le résultat correspond alors à une multiplication ou une division par une puissance de 2. Si les conditions ne sont pas remplies, le comportement de ces opérateurs est indéfini.

    - Dans le second cas, le résultat dépend de la représentation des nombres signés (il y en a trois de possibles).

    - L'utilisation de cast pour obtenir une valeur unsigned suivie de l'application d'un de ces opérateurs conduit à un comportement défini (mais peut-être pas celui souhaité) : la transformation en unsigned est définie de façon abstraite : le résultat est la valeur de départ (signed) ramenée dans la plage de l'unsigned par additions ou soustractions répétitives de la valeur maximum de l'unsigned +1. Il ne dépend pas de la représentation des entiers signés mais seulement de la largeur du type unsigned. Le comportement des opérateurs de décalage ou bit à bit est alors bien défini pour les types unsigned (si le résultat est représentable)

    Pour dire si c'est une bonne méthode, il faut savoir quel est le résultat souhaité.
    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
    Membre habitué
    Profil pro
    Inscrit en
    mars 2006
    Messages
    277
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2006
    Messages : 277
    Points : 141
    Points
    141
    Par défaut
    Merci diogene pour ta réponse,

    la transformation en unsigned est définie de façon abstraite : le résultat est la valeur de départ (signed) ramenée dans la plage de l'unsigned par additions ou soustractions répétitives de la valeur maximum de l'unsigned +1.
    C'est à dire si les types char et unsigned char son représentés sur 8 bits (1 octet), on a donc
    Pour char, l'intervalle de valeur est -127 à 127
    Pour unssigned char, l'intervalle de valeur est 0 255

    d'ou -8 en char deviendrai grâce à un cast en unsigned char -8+127+1 = +120 ??

    Es-tu d'accord ?

  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 727
    Points
    13 727
    Par défaut
    Non, la valeur max de l'unsigned char est 255
    -8+255+1 = 248
    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
    Membre habitué
    Profil pro
    Inscrit en
    mars 2006
    Messages
    277
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2006
    Messages : 277
    Points : 141
    Points
    141
    Par défaut
    OK ça marche pour les nombres négatifs, et pour les nombres positifs :
    exmple :
    char toto ;
    unsigned char tata ;

    toto = +8 ;
    tata = (unsigned char) toto ;

    tata = +8 +255 +1 = 264 or 264 est au delà de la plage.

    L'équation devrait être lors d'un cast d'un type signé en un type non signé:
    valeur non signée = valeur signée + (valeur MAX en non signée + 1) % (valeur MAX en non signée + 1)

  6. #6
    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 727
    Points
    13 727
    Par défaut
    L'équation devrait être lors d'un cast d'un type signé en un type non signé:
    valeur non signée = valeur signée + (valeur MAX en non signée + 1) % (valeur MAX en non signée + 1)
    Non, la formule est incorrecte.

    Autres exemples :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    unsigned char uc;
    uc =  555; // la valeur de uc est 555-256-256 = 43
    uc = -555; // uc = -555+256+256+256 = 213
    PS : D'un point de vue "représentation binaire", ceci correspond lorsque le nombre signé est en complément à 2 :
    - à tronquer simplement la représentation binaire pour ne garder que les lsb si le type unsigned est plus "petit" que le type signé
    - ou à étendre le bit de signe pour amener à la largeur du type unsigned lorsque celui-ci est plus "grand".
    Publication : Concepts en C

    Mon avatar : Glenn Gould

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

  7. #7
    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 : 44
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : juin 2002
    Messages : 2 165
    Points : 4 635
    Points
    4 635
    Par défaut
    Citation Envoyé par gronaze Voir le message
    toto = +8 ;
    tata = (unsigned char) toto ;

    tata = +8 +255 +1 = 264 or 264 est au delà de la plage.
    Non, tata = 8 car 8 est déjà dans la plage de valeur du nombre non signé, il n'y a pas à appliquer de translation.

    Comme l'indique diogene, les additions et soustractions servent uniquement à ramener le nombre dans la plage de valeur, s'il est déjà dans la plage, il n'y a aucun traitement à appliquer.

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

Discussions similaires

  1. Log.Message avec donnée de type "Signed 64-bit integer"
    Par Christophe.c.13 dans le forum VBScript
    Réponses: 5
    Dernier message: 17/03/2011, 12h14
  2. Addition d'entier signé sur 64 bits sur un proc 32 bits
    Par SoJaS dans le forum x86 32-bits / 64-bits
    Réponses: 3
    Dernier message: 10/08/2010, 08h22
  3. Combinaisons de type signés et non signés
    Par Hell dans le forum Langage
    Réponses: 4
    Dernier message: 01/11/2004, 20h01
  4. [FileMaker 6] Questions urgente sur type de base de donnee
    Par LAPLACE dans le forum Autres SGBD
    Réponses: 2
    Dernier message: 06/09/2004, 18h39
  5. opérateur non applicable à ce type d'opérande
    Par Amon dans le forum Langage
    Réponses: 3
    Dernier message: 11/06/2003, 19h07

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