Les opérateurs


Le C et par extension le C++ possèdent, en plus des opérateurs classiques en programmation, un grand nombre d'opérateurs qu'on ne trouvent pas dans d'autres langages. En tout, on en compte plus de 40, de quoi se régaler!

Les opérateurs sont soit unaires, soit binaires. Les opérateurs unaires ne prennent qu'une seule opérande (une opérande est une variable, une constante ou n'importe quelle valeur sur laquelle on va agir avec l'opérateur. Dans l'addition 1 + 3, 1 et 3 sont les opérandes, + est l'opérateur).

L'emplacement de l'opérande par rapport à l'opérateur dépend de ce dernier et du sens qu'on veut lui donner. Par exemple, l'opérateur de négation "!" se place uniquement devant l'opérande (exemple: !true), alors que l'opérateur d'incrémentation "++" peut se placer devant ou derrière l'opérande, suivant le contexte (exemple: ++i ou i++). Les opérateurs binaires, eux, prennent toujours deux opérandes, une avant et une après (exemple: 2+5).

Ces opérateurs servent à effectuer, avec une syntaxe plus compacte et plus claire, des opérations sur des données (variables, constantes, pointeurs...). Ces opérations vont des plus classiques (addition, soustractions...) aux plus exotiques (rotation de bits, indirection...). On peut classer tous ces opérateurs dans un certain nombre de sections.

Tout comme en mathématiques, les opérateurs obéissent à des règles de priorités.


Les opérateurs arithmétiques:

Ils permettent de faire les opérations de calcul courantes:

Addition, soustraction, multiplication, division (+, -, *, /)

Ce sont les opérations les plus courantes:

int a = 4 + 2;
int b = 3 - 4;
int c = a * b;
int d = 6 / c;

Bien entendu, avec l'opérateur de division "/", il faut que l'opérande de droite soit différente de 0.

Modulo (%)

L'opérateur binaire % (ex: a%3) renvoie, dans cet exemple, le reste de la division euclidienne de a par 3. Rappelons que la division euclidienne se compose d'un dividende, d'un diviseur, d'un quotient et d'un reste.
Exemple: dans la division euclidienne de 7 par 3, le quotient est 2 et le reste est 1 (7 = 2*3 + 1).

Voici quelques exemples numérques:
7 % 3 = 1
4 % 2 = 0

8 % 4 = 0 (car 8 = 4*2 + 0)
9 % 4 = 1
(car 9 = 4*2 + 1)
10 % 4 = 2
(car 10 = 4*2 + 2)
11 % 4 = 3
(car 11 = 4*2 + 3)
12 % 4 = 0
(car 12 = 4*3 + 0)

Ici aussi, l'opérande de droite doit être non nulle, sinon il en résulte une tentative de division par 0, résolument indigeste pour l'ordinateur.

Incrémentation, décrémentation (++, --)

Ces opérateurs ont été ajoutés à cause de leur grande utilité. En effet, l'incrémentation d'une variable est une des opérations les plus courantes, à tel point que le processeur à une instruction spéciale à cet effet.
Vous pouvez donc remplacer
a = a + 1;
par:
a++;

et de même,
a = a - 1;
par:
a--;

Il y a une différence selon qu'on place l'opérateur en suffixe (a++) ou en préfixe (++a). Regardez plutôt:

int a = 1;// On commence avec a = 1
a++; // a++ ==> a = 2
int b = a++; // b = a ==> b = 2 , puis a++ ==> a = 3
int c = ++a; // ++a ==> a = 4 , puis c = a ==> c = 4

La différence est subtile, mais importante!!! Notez que l'opérateur -- fonctionne exactement de la même manière.


Les opérateurs bit-à-bit:

Ces opérateurs permettent de manipuler avec une grande souplesse les nombres au niveau des bits (si vous n'êtes pas familier avec la notion de bit, vous pouvez consulter l'annexe Le langage binaire). Ces opérateurs sont parmi les plus rapides à l'exécution, l'ordinateur étant par nature un maître de la manipulation de bits (remarquez qu'il n'a pas vraiment choisi.) Ils est parfois plus pratique de manipuler des bits que les nombre eux-mêmes, par exemple dans l'affichage graphique ou dans la compression de données.

On ne peut utiliser ces opérateurs que sur des types entiers.

Combinaison et/ou/ou exclusif/complement à 1 (&, |, ^, ~)

Ces opérateurs permettent de comparer deux ensembles de bits selon les lois de l'algèbre de Bool. Voici les tables de vérité de chacun de ces trois opérateurs:

a
b
a & b
0
0
0
0
1
0
1
0
0
1
1
1

a
b
a | b
0
0
0
0
1
1
1
0
1
1
1
1

a
b
a ^ b
0
0
0
0
1
1
1
0
1
1
1
0

a
~a
0
1
1
0

Rotation de bits (<<, >>)

Le C++ permet de facilement décaler les bits d'un entier vers la gauche ou vers la droite. La ligne
a = (a << 2);

va décaler tous les bits de l'entier a de 2 positions vers la gauche (>> pour la droite), en introduisant à droite des 0. Examinons ce qui se passe sur 4 bits:
0011 << 1 = 0110 (3 << 1 = 6)
0011 >> 1 = 0001 (3 >> 1 = 1)

On a donc effectué une multiplication par 2 en haut (pour un décalage d'1 bit), et une division par 2 en bas. Ceci est un moyen extrêment rapide de multiplier un entier par une puissance de 2 (2, 4, 8, 16, 32...). En effet, si on veut multiplier un entier a par 8, il suffit d'écrire a = (a << 3); qui est bien plus rapide que de multiplier explicitement par 4.


Les opérateurs logiques:

En C++, une expression vraie a pour valeur 1 (comme par exemple (4 > 2)) alors qu'une expression fausse a pour valeur 0. Les opérateurs logiques ET &&, OU || et NON ! sont là pour combiner des expressions de ce types (dites expressions booléennes). Les tables de vérité sont exactement les mêmes que pour les opérateurs de combinaison (le ! remplace le ~). Essayez de deviner les résultats (vrai ou faux) de ces 4 lignes:
(3 > 2) && (1 < 5)
(2 > 2) || (2 <= 2)
!(2 > 1)
(1 == 1) || (1 == 2) || (1 == 3)

Il est a noter que tout nombre non nul est considéré comme vrai. Ainsi, l'expression (x) équivaut à (x != 0).


Les opérateurs d'affectation:

Lorqu'on a une variable, on aimerait bien sur lui affecter une valeur. C'est à ceci que servent les opérateurs d'affectation. En toute simplicité, la ligne
x = 5;

assigne la valeur 5 à x.

Il est à noter que l'affectation, comme toutes les autres opérations, renvoie une valeur: la valeur affectée. Ainsi, on peut écrire:
a = 5 + (b = 2);

Ceci correspond en fait à:
b = 2;
a = 5 + 2;

Cela permet aussi d'écrire ce genre de chose, et c'est fort appréciable :
a = b = c = d = 0;

Parfois, on veut changer la valeur d'une variable en fonction de sa valeur d'origine. Ainsi, par exemple, on peut ajouter 3 à x en écrivant:
x = x + 3;

On peut faire ceci avec pratiquement tous les opérateurs autres que les opérateurs logiques:
a = a - 5;
b = b * 10;
c = c << 2;
d = d & 3;

Ce type d'expression est tellement courant que le C, toujours soucieux de chérir ses adeptes, à introduit une syntaxe un peu particulière, mais plus compacte. Il s'agit des opérateurs compacts, dont voici la liste complète avec leurs équivalents:

a = a + b a += b
a = a - b a -= b
a = a * b a *= b
a = a / b a /= b
a = a % b a %= b
a = a << 1 a <<= 1
a = a >> 1 a >>= 1
a = a & b a &= b
a = a | b a |= b
a = a ^ b a ^= b
a = a + 1 a++
a = a - 1 a--

Ces notations peuvent vous paraître inhabituelles si vous avez déjà programmé dans d'autres langages, mais elles vous feront gagner pas mal de temps et vous permettront de clarifier votre code.


Les opérateurs de comparaison:

Ces opérateurs sont là pour nous permettre de comparer des valeurs numériques. Deux opérandes et l'un de ces opérateurs constituent une expression booléenne dont le résultat est 1 ou 0 (cf. Les opérateurs logiques). Ces opérateurs sont ceux des mathématiques classiques, avec une petite variation sur l'égalité et la différence:

a > b a est strictement supérieur à b
a >= b a est supérieur ou égal à b
a < b a est strictement inférieur à b
a <= b a est inférieur ou égal à b
a == b a est égal à b
a != b a est différent de b

Attention de ne pas confondre l'opérateur d'affectation (=) avec l'opérateur d'égalité (==)!


L'opérateur conditionnel:

En C (ainsi qu'en C++, bien sûr), il n'est pas rare d'avoir à écrire ce genre de code:

if(y == 0)
x = 1;
else
x = 2;

En fait, en voici la forme généralisée:

if(condition)
x = valeur1;
else
x = valeur2;

Ces 4 lignes peuvent être condensées grâce à l'opérateur conditionnel, là encore fourni comme une sucrerie pour le programmeur (qui, nous le rappelons, est gourmand et paresseux par nature :-), dont voici la syntaxe:

x = condition ? valeur1 : valeur2;

Ainsi, le premier exemple peut être résumé par:

x = (y == 0) ? 1 : 2;


Table de priorité des opérateurs:

Vous savez certainement qu'en mathématique, il existe des priorités entre les opérations: la multiplication et la division sont prioritaires sur l'addition et la soustraction. Ainsi, on peut écrire sans ambiguité 2 * 4 + 5 * 3, qui revient à écrire 8 + 8, et non 2 * 9 * 3. En programmation, il existe également des priorités entre les opérateurs, afin de ne pas devoir placer des tas de parenthèses partout pour lever les amiguités. Voici la table de priorité des opérateurs, le plus prioritaire étant placé en haut:

++, --, ~, !, -(unaire)
*, /, %
+, -
<<, >>
<, <=, >, >=
==, !=
&, ^, |
&&, ||
?: (op. conditionnel)
=, +=, -=, *=, /=, %=, >>=, <<=, &=, |=, ^=

Ainsi, avec ces règles de priorité, il devient suffisant d'écrire x = 4 + 5, sans aucune parenthèses et sans aucune ambiguité: d'abord on additionne 4 et 5, puis on affecte le résultat à x.

Cependant, s'il n'est pas absolument nécessaire de mettre des parenthèses grâce aux règles de priorités, les ignorer totalement n'est pas une bonne idée. Voici un exemple pour vous illustrer ceci:
x++ * 4 == 2 | y * z + 10 + -15

A première vue, cette expression (pas franchement utile, je vous l'accorde, mais elle nous sert d'exemple) n'est pas facile à lire et à déchiffrer. Vous pourriez en donner le résultat d'un seul coup, connaissant x, y et z? Ceci est déjà nettement plus clair:
((x++ * 4) == 2) | (y * z + 10 + (-15))

Il existe également d'autres opérateurs en C++, notemment l'indirection (->) avec les pointeurs. Cependant, leurs règles de priorité ne sont pas listées ici pour simplifier un peu le tableau. Avec l'experience, vous saurez placer intuitivement les parenthèses aux endroits stratégiques.


Voir aussi: Le langage binaire - Les types de variables


Haut de la page