TODO modifier

brouillons modifier

Ceci est un brouillon pour le chapitre Opérateurs du livre de C.


Reste à faire:

  • 13 et 5 ne sont pas des bons exemples: ils n'utilisent que les 4 premiers bits...
  • exemples d'utilisation réelle (masques...)
  • mise en page des exemples plus lisible

Opérateurs binaires modifier

Pour manipuler les nombres, le C fournit les opérateurs mathématiques usuels (addition, multiplication, modulo...), mais aussi d'autres opérateurs, qui agissent sur la représentation en base 2 des valeurs, dits opérateurs binaires. Il faut bien comprendre qu'en C, ces opérateurs agissent sur la valeur et non sur la représentation des nombres en machine. En particulier, l'odre des bits au sein des octets, ou l'ordre des octets en mémoire n'agissent pas sur le résultat de ces opérateurs.

Cependant, pour mieux se représenter ces opérateurs, on suppose ici que les unsigned int sont codés sur 16 bits, et on écrit ces bits du poids fort au poids faible. Par exemple, la valeur décimale 13 s'écrit 1101 en binaire, et 0000 0000 0000 1101 la représente telle que stockée dans un unsigned int, sous les hypothèses précédentes. Mais il faut bien souligner que les propriétés des opérateurs étudiés dans ce paragraphe ne dépendent pas de ces hypothèses, qui ne sont là que pour illustration.

Nous travaillerons sur des types non signés, car les opérateurs binaires sont complètement définis sur ces types, et leur comportement sur les nombres négatifs est pour la plupart imprévisible (ou au moins dépendant de l'implémentation). De plus, non avons pris l'exemple du type unsigned int, car les promotions entières sont effectuées sur tous les opérandes, et on ne traitera donc jamais directement des opérandes de types plus petits.

Pour travailler en binaire, le C offre les opérateurs suivants:

  • décalages à gauche et à droite;
  • ET, OU et OU exclusif;
  • négation;
  • ainsi que des opérateurs d'affectation correspondants.

Décalage à droite et à gauche modifier

Les opérateurs de décalage à gauche (<<) et à droite (>>) permettent d'agir sur l'écriture binaire d'un nombre en décalant les bits. Par exemple, la valeur 13, ou 0000 0000 0000 1101, devient, après décalage d'un bit vers la gauche, 0000 0000 0001 1010, soit 26, et 0000 0000 0000 0110, soit 6, après un décalage d'un bit vers la droite. La syntaxe en C pour effectuer des décalages est illustrée par le code suivant:

    unsigned int x = 13;     /* 0000 0000 0000 1101 */
    unsigned int y = x << 1; /* 0000 0000 0001 1010 */
    /* y vaut maintenant 26 */
    unsigned int z = x >> 1; /* 0000 0000 0000 0101 */
    /* z vaut maintenant 6 */

La seconde ligne effectue un décalage à gauche (<<) de la valeur de l'expression se trouvant à gauche de l'opérateur (x) par le nombre de bits spécifiés à droite (1). La troisième ligne montre que l'opérateur >> agit de même, en décalant à droite.

On remarque ainsi que décaler d'un bit vers la gauche en binaire revient à multiplier la valeur par 2 (car in * 2n + ... + i0 * 20 devient in * 2n+1 + ... + i0 * 21 + 0 * 20), et décaler à droite d'un bit revient à effectuer une division entière par 2. Dans le cas du comportement à la limite, si, par exemple, on veut décaler la valeur 61455 (1111 0000 0000 1111) de 4 bits vers la gauche, les bits qui "sortent" sont simplement "oubliés", et on obtient 0000 0000 1111 0000, soit 240. En fait, l'opération se fait, comme pour les autres opérations entières, modulo le nombre maximal représentable augmenté de 1:

    61455 << 4 = 61455 * 2^4   (^ signifie ici "élevé à la puissance")
               = 61455 * 16
               = 983280

et 983280 modulo 65536 donne 240.

Par contre, le décalage d'un nombre de bits négatifs, ou supérieur ou égal à la taille du type est imprévisible. Par exemple, vouloir décaler une valeur de type unsigned int de -1, 16 ou 17 bits dans un sens ou dans l'autre. Mais vouloir décaler une valeur de type unsigned long de 16 bits est toujours parfaitement défini.

ET, OU et OU exclusif modifier

Ces opérateurs fournissent les opérations logiques (ou booléennes) usuelles, mais en travaillant bit à bit sur leurs opérandes. Le ET se note &, OU se note |, et le ou exclusif se note ^. Comme d'habitude en C, 0 compte pour une valeur fausse, et 1 pour vrai.

En se limitant à un bit, on obtient donc les tables suivantes pour ces opérateurs :

0 & 0 == 0          («faux et faux» renvoie la valeur «faux») 
0 & 1 == 1 & 0 == 0 («faux et vrai» renvoie la valeur «faux», de même pour «vrai et faux») 
1 & 1 == 1          («vrai et vrai» renvoie la valeur «vrai») 
0 | 0 == 0          («faux ou faux» renvoie la valeur «faux») 
0 | 1 == 1 | 0 == 1 («faux ou vrai» renvoie la valeur «vrai», de même pour «vrai ou faux») 
1 | 1 == 1          («vrai ou vrai» renvoie la valeur «vrai») 
0 ^ 0 == 0          («faux xou faux» renvoie la valeur «faux») 
0 ^ 1 == 1 ^ 0 == 1 («faux xou vrai» renvoie la valeur «vrai», de même pour «vrai xou faux») 
1 ^ 1 == 0          («vrai xou vrai» renvoie la valeur «faux») 

Si on revient à un cas concret de type codé sur 16 bits, on peut obtenir, par exemple, les cas suivants. 13 & 5 vaut 5, car :

     0000 0000 0000 1101 : 13
ET
     0000 0000 0000 1001 :  5
=    0000 0000 0000 1001 :  5

De même, 13 | 5 vaut 13, car:

     0000 0000 0000 1101 :  13
OU
     0000 0000 0000 1001 :   5
=    0000 0000 0000 1101 :  13

Et 13 ^ 5 vaut 4, car:

     0000 0000 0000 1101 :  13
XOU
     0000 0000 0000 1001 :   5
=    0000 0000 0000 0100 :   4

Négation modifier

L'opérateur de négation binaire (~) effectue une négation bit à bit de son argument. Par exemple,

0000 0000 0000 1101 :    13

devient

1111 1111 1111 0010 : 65522

L'usage de cet opérateur nécessite une attention particulière, car on remarquera que la valeur du résultat dépend de la taille du type utilisé. Suivant la taille du type unsigned int, l'expression ~ 13U peut avoir des valeurs différentes: 65522 si le type est codé sur 16 bits et 4294967282 s'il est codé sur 32 bits.

Opérateurs d'affectation modifier

Les opérateurs d'affectation correspondant aux opérateurs binaires sont définis de manière similaire aux autres opérateurs d'affectation.