Le langage C intègre de nombreux opérateurs. Certains sont des opérateurs unaires : ils agissent sur un seul argument. D'autres sont des opérateurs binaires : ils combinent deux arguments. Il existe même un opérateur ternaire agissant sur trois arguments.
Dans une expression, la priorité entre les opérateurs est définie par la norme
ANSI. Le tableau 4.1 donne à titre indicatif tous les opérateurs
classés par ordre croissant de priorité et en spécifiant, pour chaque groupe
d'opérateurs de priorité égale, le sens d'évaluation. Un opérateur unaire est
toujours plus prioritaire que le même opérateur binaire : par exemple,
l'opérateur -
unaire (opposé) est prioritaire sur l'opérateur -
binaire (soustraction).
Le sens d'évaluation spécifie dans quel ordre sont évaluées des expressions de même niveau de priorité. Par exemple, l'expression :
est équivalente à :
a = b - c - d;
puisque l'opérateur
a = (b - c) - d;
-
(binaire) est évalué de gauche à droite.
En revanche, l'expression :
est équivalente à :
a -= b -= c;
puisque l'opérateur -= est évalué de droite à gauche.
a -= (b -= c);
À tout programmeur (quel que soit son niveau), il est fortement conseillé d'utiliser les parenthèses pour gérer explicitement l'ordre d'utilisation des opérateurs plutôt que de se fier à sa connaissance de ce tableau de priorité. Cela évite de se tromper et rend surtout le programme plus lisible.
Il existe 7 opérateurs arithmétiques. Ils sont donnés dans le tableau 4.2.
Ces opérateurs font le calcul demandé et le type de la valeur produite dépend
de celui (ou ceux) de l'opérande (ou des opérandes). Par exemple, la résultat
d'une division sera de type int
si ses deux opérandes sont eux-mêmes de
type int
. Par contre, si au moins un des deux opérandes est de type
double
alors le résultat sera de type double
. La division entre
deux entiers est donc une division entière.
Dans l'exemple suivant, a
vaut 12 et b
vaut 14 :
int x = 14, a;
double y = 14, b;
a = (x / 4) * 4;
b = (y / 4) * 4;
On peux appliquer à une variable des opérateurs d'incrémentation ou de décrémentation (tableau 4.3). C'est une incrémentation (ou une décrémentation) d'une unité. Le contenu de la variable est modifié par ces opérateurs.
Ces opérateurs peuvent être placés avant ou après le nom de la variable. Si ils sont placés avant, la variable est incrémentée (ou décrémentée) avant l'utilisation de sa valeur. Si ils sont placées après, la variable est incrémentée après l'utilisation de sa valeur.
Dans l'exemple suivant, x
vaut 11 ainsi que n
.
int x, n = 10;
x = ++n;
Dans l'exemple suivant, x
vaut 10 et n
vaut 11.
int x, n = 10;
x = n++;
Il est conseillé de ne pas abuser de cette possibilité pour ne pas rendre les programmes incompréhensibles.
Les opérateurs bit à bit effectue une opération logique (et, ou, ou exclusif, négation) sur chacun des bits (tableau 4.4).
On utilise souvent ces opérateurs pour masquer certain bits (en les mettant à zéro) ou pour forcer leur valeur (en les mettant à 1).
Dans l'exemple suivant, seuls le troisième bit et le quatrième
bit de n
conservent leur valeur. Tous les autres sont
mis à zéro (
12 = 8 + 4 = 24 + 23).
n = n
&
12;
Ces opérateurs ne s'appliquent que sur des valeurs entières.
En C, il existe deux opérateurs de décalage (tableau ). Ces deux opérateurs décalent les bits composant une valeur vers la gauche ou vers la droite.
Le premier argument est la valeur à décaler tandis que le
second argument est le nombre de décalage à effectuer. Les
bits qui sortent de la valeur sont perdus. Les nouveaux bits
sont mis à zéro. Un décalage à gauche d'un bit correspond à
une multiplication par deux. Alors qu'un décalage à droite
d'un bit correspond à une division entière par deux. Dans
l'exemple suivant, on décale la valeur de n
de 2 bits
vers la droite :
n = n >> 2;
Il est possible de comparer les valeurs de deux expressions grâce à 6 opérateurs de comparaison (tableau 4.6).
Par convention, le résultat de ces opérateurs est 1
(vrai)
ou 0 (faux) . Par exemple, dans le programme suivant, x
vaut
1
.
int x = (3*4) < (4*5);
Les opérations logique (tableau 4.7) considèrent un
opérande comme faux si sa valeur est 0
et vrai dans tous les autres
cas.
Par convention, le résultat de ces opérateurs est 1
(vrai)
ou 0 (faux) . Par exemple, dans le programme suivant, x
vaut
1
et y
vaut 0
:
int n = 0, m = 10, x, y;
x = (n < 20)&&
m;
y = !((n > 20) || (m == 10));
Nous avons déjà dit qu'on utilisait l'opérateur =
pour
affecter le résultat d'une expression à une variable. Il est
possible de préfixer l'opérateur =
par la plupart des
opérateurs binaires. On obtient ainsi un nouvel
opérateur d'affectation qui effectuera d'abord le calcul entre
l'expression et la valeur actuelle de la variable puis
affectera le résultat à la variable.
Les deux lignes C suivantes sont donc équivalentes :
a *= b + 10;
a = a * (b + 10);
Le résultat d'une affectation est la nouvelle valeur de la
variable et il peut être utilisé dans une autre expression.
Dans l'exemple suivant a
vaut 10 et b
vaut 20 :
b = 2 * (a = 10);
Il existe un seul opérateur ternaire en C. Cet opérateur
permet d'écrire des expressions conditionnelles. L'expression
conditionnelle débute par un test suivi du caractère ?
puis la valeur lorsque le test est vrai puis le caractère
:
et enfin la valeur lorsque le test est faux.
Par exemple, dans l'exemple suivant, a
vaut 3.14 et
b
vaut 5 :
y = 100;
a = (y < 200) ? 3.14 : 25;
b = (a > 3) ? ((y > 200) ? 10.1 : 5.0) : 123.0;
Pour manipuler les tableaux, les structures, les pointeurs et la mémoire, il existe cinq opérateurs (tableau 4.8). Nous en donnons la liste ici mais leur utilisation est plus détaillée dans le chapitre consacré aux tableaux, pointeurs et structures (page ).
Nous avons vu que, lors d'une division, les types des opérandes étaient importants pour déterminer le type du résultat. Ceci est vrai pour toutes les opérations en C. Le C effectue des conversions de type implicites lorsqu'elles sont nécessaires. On peut forcer la conversion d'un type vers un autre grâce à l'opérateur de conversion explicite.
Voici les règles simples permettant de déterminer les conversion implicites utilisées en C. Ces règles sont appliquées dans l'ordre cité :
double
, convertir
l'autre en double
.
float
, convertir
l'autre en float
.
char
et
short
en int
.
long
, convertir l'autre
en long
.
Lorsque la valeur d'une expression est un argument d'une fonction, la valeur est automatiquement convertie vers le type de l'argument.
Il est possible de spécifier une conversion explicitement
(pour effectuer une division entière entre deux double
par exemple). Il suffit de précéder une expression par le
nouveau type mis entre parenthèse. Dans l'exemple suivant,
c
vaut 3 (la division est une division entière
puisqu'on a converti explicitement les deux opérandes en
int
. Le résultat est automatiquement converti en
double
puisque c
est de type double
) :
double a = 10, b = 3;
double c;
c = ((int) a) / ((int) b);