Les opérateurs
Terminologie
Un opérateur (operator) en C++ est une fonction dont l’écriture utilise un ou deux caractères spéciaux. On peut citer l’exemple des opérateurs mathématiques : +, -, ×, ÷ où l’écriture 4+7 est interprété par le compilateur comme l’appel de la fonction : Opérateur+(4,7). En dehors des opérateurs arithmétiques, on trouve aussi :
() l’opérateur d'appel de fonction (function call operator) comme dans l’écriture sin(2)
[] l’opérateur d'indexation (subscript operator) permettant l’accès à l’élément d’un tableau : T[4]
= l’opérateur d'affectation (assignment operator) : a = 4;
. l’opérateur d'accès aux membres (member access operator) utilisé pour accéder aux variables/fonctions d’un objet : t.a
Il existe trois catégories d’opérateurs établis suivant le nombre de paramètres utilisés :
Les opérateurs binaires (binary operator) : les plus courants, ils prennent deux arguments comme dans le cas des opérateurs arithmétiques.
Les opérateurs unaires (unary operator) : plus rares, on trouve ici les opérateurs acceptant un seul paramètre. Le plus connu est l’opérateur ++ servant à incrémenter une variable ou encore l’opérateur ! servant à la négation dans une condition.
les opérateurs ternaires : il n’en existe qu’un et nous le considérons hors programme.
Le terme opérande (operand) désigne tout élément pouvant être utilisé par un opérateur. Les opérandes ne correspondent pas forcément à une valeur. Par exemple, dans l’écriture a+4; l’opérande de gauche correspond à une variable.
Une expresssion (expression) est un terme désignant une séquence d’opérateurs et d’opérandes. Cette définition semble assez intuitive pourtant elle cache de nombreuses réalités bien plus complexes que les expressions arithmétiques :
L’écriture toto() est ainsi une expression. Son type de retour correspond au type de retour de la fonction toto.
L’écriture T[i] est ainsi une expression. Son type de retour correspond au type des éléments du tableaux. Ainsi, l’écriture T[T[i]] est une expression au même titre que sin(cos(t)).
L’écriture a=3 est une expression. Cela peut paraître étrange car aucun calcul n’est réellement effectué, mais le signe = reste un opérateur binaire, il est donc dans le langage C++ similaire à l’écriture de 2+3 !
Note
Fait étonnant : l’écriture a=3 est une expression retournant une valeur au même titre que l’opérateur + !!! Cette valeur correspond à la valeur transmise durant l’affectation soit ici la valeur 3. Ainsi, l’écriture a = b = 3 se lit a = (b = 3). De cette façon, la variable a prend comme valeur le résultat de l’expression b=3 et le chaînage de plusieurs affectations peut fonctionner !
Une expression peut regrouper des littéraux, des variables, des opérateurs et des appels de fonctions que le langage interprète pour produire un résultat. Ce processus, comme pour les expressions mathématiques, est appelé évaluation (evaluation). On peut ainsi parler du type d’une expression, il correspond donc au type du résultat de son évaluation.
Note
Qu’est-ce qui n’est pas une expression ? Difficile de répondre, car effectivement dans cette approche, tout ce que l’on trouve dans un programme correspond à l’écriture d’une expression !!! On peut cependant citer les structures de contrôle comme if et for.
Indiquez si les affirmations suivantes sont vraies ou fausses :
Un opérateur unaire possède un seul paramètre.
Un opérateur se comporte comme une fonction.
Un opérateur binaire retourne un résultat binaire true/false.
Les opérations mathématiques sont traitées comme des opérateurs.
Une opérande désigne un appel de fonction.
Un opérateur binaire s’applique uniquement sur des valeurs binaires.
Dans une expression, on peut trouver des variables, des littéraux, des appels de fonctions.
L’instruction if (…) est une expression conditionnelle.
L’écriture a=toto() est une expression.
L’évaluation consiste à déterminer le résultat d’une expression.
Principe de fonctionnement
Le langage C++ s’articule autours des opérateurs. Leur logique interne est très proche des opérateurs arithmétiques que vous avez l’habitude d’utiliser. On peut consulter la liste des opérateurs arithmétiques.
Note
L’opérateur modulo désigne le reste de la division de a par b, par exemple 8%5 = 3 ou encore 16%5=1.
Note
Le signe - correspond à deux opérateurs : l’opérateur binaire dans l’expression a-5 et l’opérateur unaire dans l’écriture a=-b.
La priorité des opérateurs
A chaque opérateur du C++ est associé un niveau de priorité (precedence). Par convention, les opérateurs avec une priorité plus basse sont évalués en premier. Ainsi, on remarque que l’opérateur d’addition a une priorité 6, il est donc moins prioritaire que la multiplication avec une priorité de 5. De cette façon, dans l’expression 3*6+7, l’évaluation effectue le calcul suivant : (3*6)+7.
Note
On peut remarquer que l’opérateur d’appel de fonction () a une priorité de niveau 2, soit quasiment la plus prioritaire du langage.
L’utilisation des parenthèses
Il est possible d’utiliser une paire de parenthèses dans une expression. Ces parenthèses ne correspondent pas à un opérateur du C++ à proprement parler. Elles ont pour rôle de définir une sous-expression à l’intérieur de l’expression courante. Ainsi, l’expression entre parenthèses est d’abord évaluée et son résultat est ensuite transmis à l’expression principale.
Le sens d’évaluation
Lorsque l’on trouve une expression contenant des + et des - comme dans 3-6+7-4, il faut savoir dans quel ordre sont effectués les calculs. En effet, le résultat de 3-((6+7)-4) n’a rien à voir avec celui de (3-6)+(7-4). Dans cet exemple, la règle sur les priorités ne s’appliquent pas car les opérateurs + et - ont des priorités équivalentes. Dans ce cas précis, nous appliquons la règle suivante : lorsque deux opérateurs ont des priorités équivalentes, l’évaluation se fait de gauche à droite. Ainsi, c’est le sens de lecture qui guide les calculs et dans l’expression 3-6+7-4 le calcul effectué est : (((3-6)+7)-4).
Note
Il existe quelques opérateurs dont l’évaluation se fait de droite à gauche ! Pour les connaître, vous pouvez rechercher les opérateurs dont l’associativité se fait de droite à gauche. On peut citer par exemple l’opérateur d’affectation =. Ainsi dans l’écriture a=b=3, il faut bien effectuer en premier b=3 et ensuite a=… et non l’inverse.
Pour chacune des expressions, sa valeur :
Expression |
Valeur |
---|---|
2 + 3 * 2 |
|
2 + ( 5 % 2 ) |
|
(4+5)*7 |
|
(1+3)*(4+5) |
|
5+2-3+6-8 |
|
(4*3+2)-(3*2+2) |
Opérateurs d’affectation
Parmi les opérateurs d’affectation, on trouve +=, -=, *= ou encore /=. Ces opérateurs permettent une écriture plus compacte et plus lisible du code. Nous vous conseillons donc de les utiliser.
Sachant que la variable a vaut 5, donnez sa valeur après l’évaluation de chaque affectation :
Expression |
Valeur |
---|---|
a += 3 |
|
a -= 2 |
|
a *= 2+1 |
Opérateurs de pré/post incrémentation
Nous présentons les opérateurs de pré et post incrémentation et décrémentation.
Lorsque l’opérateur ++ est à gauche de la variable, il s’agit de l’opérateur de préincrémentation : la variable est augmentée de 1 puis sa nouvelle valeur est retournée comme résultat.
Lorsque l’opérateur ++ est à droite, il s’agit de l’opérateur de postincrémentation. De la même manière, la variable est augmentée de 1 mais cette fois ce sera sa valeur initiale qui sera retournée.
Note
Tous ces opérateurs s’appliquent sur une variable et non sur une valeur. Ainsi l’écriture 4++ n’a aucun sens.
Dans la pratique, on utilise 99% du temps les opérateurs de post-incrémentation/décrémentation.
Sachant que la variable a vaut 5 avant l’exécution de chaque ligne, donnez l’affichage ainsi que la valeur de a après l’exécution :
Code |
Affichage |
Valeur de a après l’exécution |
---|---|---|
std::cout << a++; |
||
std::cout << a--; |
||
std::cout << --a; |
||
std::cout << ++a; |
Note
Il y a une petite subtilité sur le type de retour des opérateurs de pré/post incrémentation. Pour l’opérateur de pré-incrémentation, le type de retour est un référence sur la variable courante. Ceci permet de chaîner cet opérateur, l’écriture ++++a est donc possible bien que peu lisible. Pour l’opérateur de post-incrémentation, le type de retour est une valeur ne permettant pas de chaîner cet opérateur : l’écriture a++++ est incorrecte. Respirez et relisez ce passage :)
Priorité des opérateurs
Nous résumons ci-dessous la priorité des principaux opérateurs :
Priorité |
Opérateur |
Nom |
---|---|---|
1 |
:: |
Résolution de portée |
2 |
a++ a-- |
Opérateurs de post incrémentation/décrémentation |
a() |
Opérateur d’appel de fonction |
|
a[] |
Opérateur d'indexation |
|
3 |
++a --a |
Opérateurs de pré incrémentation/décrémentation |
-a |
Opérateur moins unaire |
|
! |
Opérateur NON logique |
|
5 |
a*b a/b a%b |
Opérateurs arithmétiques : multiplication division modulo |
6 |
a+b a-b |
Opérateurs arithmétiques : addition et soustraction |
9 |
< <= > >= |
Opérateurs de comparaison |
10 |
== != |
Opérateurs d’égalité et de différence |
14 |
&& |
Opérateur ET logique |
15 |
|| |
Opérateur OU logique |
16 |
= += -= *= /= |
Opérateurs d’affectations |