Operators ********* .. include:: ../BoutonGoogleTrad.rst Le langage C++ ============== Dans un programme C++, on rencontre plusieurs grandes catégories d’éléments : - Des opérateurs (:cppterm:`operator`) comme :cpp:`+`, :cpp:`-` ou :cpp:`<` - Des structures de contrôle (:cppterm:`control statement`) : :cpp:`if`, :cpp:`for`... - Des littéraux (:cppterm:`literals`) comme :cpp:`42`, :cpp:`3.14`, :cpp:`'a'`, :cpp:`"Bonjour"`, :cpp:`true` qui représentent des valeurs directement écrites dans le code - Des symboles de ponctuation (:cppterm:`punctuators`) comme :cpp:`; ( )` et :cpp:`{ }` qui structurent le programme - Des commentaires (:cppterm:`comments`) Les opérateurs arithmétiques ============================ La logique que nous allons voir dans ce chapitre fonctionne de manière similaire à ce que nous connaissons déjà en mathématiques. En effet, une opération mathématique prend une ou plusieurs valeurs, appelées **opérandes** (:cppterm:`operand`) et produit une nouvelle valeur en sortie. Voici un exemple pour l'addition, examinez ce tableau car nous allons reprendre ce format de présentation par la suite : .. raw:: html
.. list-table:: :widths: 30 10 10 25 25 * - Opérateur - Symbole - Exemple - Opérandes - Résultat * - **Opérateur + d'addition arithmétique** :cppterm:`Addition operator` - :cpp:`+` - :cpp:`4+x` - Gauche : le littéral 4 Droite : la variable :cpp:`x` - la somme de 4 et de la valeur de :cpp:`x` .. raw:: html
Lorsque l'on regroupe plusieurs opérations dans une seule ligne, éventuellement en ajoutant des parenthèses, on obtient une **expression** (:cppterm:`expression`) ; par exemple : :cpp:`4 × (3 + x)`. Une expression peut inclure des variables mais aussi des appels de fonctions : :cpp:`sin(4 × (3 + x))+sqrt(x)`. Les opérateurs ============== Opérateur vs fonction --------------------- La distinction entre fonction et opérateur est fine car ces deux notions sont proches, cependant : - Si l'opération est intégrée dans le langage C++, on parle d'opérateur : :cpp:`+`, :cpp:`\*`, :cpp:`/` ... - Si l'opération est définie dans le programme ou fournie par une bibliothèque, on parle de fonction : :cpp:`sin()`, :cpp:`cos()`, :cpp:`sqrt()`... Terminologie ------------ On parle de : - **Opérateur binaire** (:cppterm:`binary operator`) : lorsque l'opérateur accepte deux opérandes comme dans le cas des opérateurs arithmétiques. - **Opérateur unaire** (:cppterm:`unary operator`) : lorsque l'opérateur accepte une seule opérande. Les opérateurs unaires les plus connus sont : - L'opérateur :cpp:`++` servant à incrémenter une variable - L'opérateur :cpp:`!` servant à la négation dans une condition Remarque : le même signe peut être associé à plusieurs opérateurs, par exemple : - L'opérateur binaire :cpp:`-` présent dans l'écriture :cpp:`a-5` - L'opérateur unaire :cpp:`-` présent dans l'écriture :cpp:`a = -b` Logique ------- Les opérateurs du C++ ne se limitent pas aux calculs, ils forment une famille bien plus large. Ainsi, la plupart des syntaxes que vous utilisez correspondent en réalité à des opérateurs. Voici quelques exemples : .. raw:: html
.. list-table:: :header-rows: 1 :widths: 30 10 10 25 25 * - Opérateur - Symbole - Exemple - Opérandes - Résultat * - **Opérateur d\'appel de fonction** :cppterm:`Function call operator` - :cpp:`( )` - :cpp:`sin(2)` - Gauche : le nom de la fonction Droite : le littéral :cpp:`2` - La valeur renvoyée par la fonction :cpp:`sin()` * - **Opérateur d'indexation** :cppterm:`Subscript operator` - :cpp:`[]` - :cpp:`T[4]` - Gauche : un tableau Droite : un indice - La valeur située à l'indice indiqué dans le tableau * - **Opérateur d'accès aux membres** :cppterm:`Member access operator` - :cpp:`.` - :cpp:`cercle1.rayon` - Gauche : un objet Droite : le nom d'un membre - La valeur de ce membre * - **Opérateur de résolution de portée** :cppterm:`Scope resolution operator` - :cpp:`::` - :cpp:`std::cout` - Gauche : un espace de noms (ici :cpp:`std`) Droite : le nom d'un membre (ici :cpp:`cout`) - Le membre :cpp:`cout` de l'espace de noms :cpp:`std` * - **Opérateur d\'affectation** :cppterm:`Assignment operator` - :cpp:`=` - :cpp:`a = 4`; - Gauche : la variable :cpp:`a` Droite : le littéral :cpp:`4` - Stocke la valeur :cpp:`4` dans :cpp:`a` Retourne l'opérande de droite .. raw:: html
Fait amusant : l'opérateur d'affectation :cpp:`=` renvoie comme valeur l'opérande de droite. Quel est l'intérêt ? Prenez cela comme une anecdote, c’est ce qui permet à l'écriture :cpp:`a = b = 4` de fonctionner. Ainsi, la première affectation :cpp:`(b=4)` retourne la valeur :cpp:`4` et l'injecte vers la 2ème affectation :cpp:`a=...`. Expression ========== Une **expression** (:cppterm:`expression`) est une combinaison de littéraux, de variables, d'opérateurs et d'appels de fonctions que le langage évalue pour produire un résultat. La valeur obtenue posséde un type, on peut donc par extension parler du **type d'une expression**. Au même titre que :cpp:`2 + 4`, les écritures suivantes sont également des expressions : .. list-table:: :widths: 25 25 25 25 * - :cpp:`42` - :cpp:`x` - :cpp:`++i` - :cpp:`tab[i + 1]` * - :cpp:`std::cin` - :cpp:`a = 4` - :cpp:`x > y && x < z` - :cpp:`!trouve` * - :cpp:`(a + b) * c` - :cpp:`matrice[i][j]` - :cpp:`new Cercle()` - :cpp:`x += 5` .. quiz:: compehensionOperateur :title: Terminologie Indiquez si les affirmations suivantes sont vraies ou fausses : * :quiz:`{"type":"TF","answer":"T"}` Un opérateur unaire possède un seul paramètre. * :quiz:`{"type":"TF","answer":"T"}` Un opérateur se comporte comme une fonction. * :quiz:`{"type":"TF","answer":"F"}` Un opérateur binaire retourne un résultat binaire true/false. * :quiz:`{"type":"TF","answer":"T"}` Les opérations mathématiques sont traitées comme des opérateurs. * :quiz:`{"type":"TF","answer":"F"}` Une opérande désigne un appel de fonction. * :quiz:`{"type":"TF","answer":"F"}` Un opérateur binaire s'applique uniquement sur des valeurs binaires. * :quiz:`{"type":"TF","answer":"T"}` Dans une expression, on peut trouver des variables, des littéraux, des appels de fonctions. * :quiz:`{"type":"TF","answer":"F"}` L'instruction :cpp:`if (...)` est une expression conditionnelle. * :quiz:`{"type":"TF","answer":"T"}` L'écriture :cpp:`a=toto()` est une expression. * :quiz:`{"type":"TF","answer":"T"}` L'évaluation consiste à déterminer le résultat d'une expression. Ne pas utiliser de majuscules dans la suite : * Donnez le nom de cet opérateur : :cpp:`a=4` : :quiz:`{"type":"FB","answer":"assignment operator"}` * Donnez le nom de cet opérateur : :cpp:`a[4]` : :quiz:`{"type":"FB","answer":"subscript operator"}` * Donnez le nom de cet opérateur : :cpp:`v.dr` : :quiz:`{"type":"FB","answer":"member access operator"}` Principe de fonctionnement ========================== Le langage C++ s'articule autours des opérateurs. La priorité des opérateurs -------------------------- A chaque opérateur du C++ est associé `un niveau de priorité `_ (:cppterm:`operator precedence`). Par convention, un opérateur de **priorité 1** est évalué en premier. Ainsi, l'opérateur d'addition avec une priorité de 6 est moins prioritaire que la multiplication avec une priorité de 5. De cette façon, dans l'expression :cpp:`3*6+7`, l'évaluation effectue le calcul suivant : :cpp:`(3*6)+7`. .. note:: L'opérateur d'appel de fonction :cpp:`()` a une priorité de niveau 2, soit quasiment la haute priorité 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 :cpp:`+` et des :cpp:`-` comme dans :cpp:`3-6+7-4`, il faut savoir dans quel ordre sont effectués les calculs. En effet, le résultat de :cpp:`3-((6+7)-4)` n'a rien à voir avec celui de :cpp:`(3-6)+(7-4)`. Comme les les opérateurs :cpp:`+` et :cpp:`-` ont des priorités équivalentes, on applique la règle suivante : **lorsque deux opérateurs ont des priorités équivalentes, l'évaluation se fait de gauche à droite** (:cppterm:`Left-to-right evaluation`). Ainsi, c'est le sens de lecture (de gauche à droite) qui guide les calculs. Dans l'expression :cpp:`3-6+7-4`, le calcul effectué est donc : :cpp:`(((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 :cpp:`=`. Ainsi dans l'écriture :cpp:`a=b=3`, il faut bien effectuer en premier :cpp:`b=3` et ensuite :cpp:`a=...` et non l'inverse. .. quiz:: evalOperateur :title: Expressions numériques L'opérateur modulo désigne le reste de la division de :cpp:`a` par :cpp:`b`, par exemple :cpp:`8%5 = 3` ou encore :cpp:`16%5=1`. Pour chacune des expressions, donnez sa valeur : .. csv-table:: :header: Expression, Valeur :widths: 10, 10 :delim: ! :cpp:`2 + 3 * 2` ! :quiz:`{"type":"FB","answer":"8"}` :cpp:`2 + ( 5 % 2 )` ! :quiz:`{"type":"FB","answer":"3"}` :cpp:`(4+5)*7` ! :quiz:`{"type":"FB","answer":"63"}` :cpp:`(1+3)*(4+5)` ! :quiz:`{"type":"FB","answer":"36"}` :cpp:`5+2-3+6-8` ! :quiz:`{"type":"FB","answer":"2"}` :cpp:`(4*3+2)-(3*2+2)` ! :quiz:`{"type":"FB","answer":"6"}` Priorité des opérateurs ----------------------- A titre indicatif, nous présentons la priorité des principaux opérateurs : .. csv-table:: :widths: 1, 1, 5 :header: Priorité, Opérateur, Nom 1, :cpp:`\:\:` , Résolution de portée 2, :cpp:`a++ a-\-`, Opérateurs de post incrémentation/décrémentation ,:cpp:`a()`, Opérateur d'appel de fonction ,:cpp:`a[]`, Opérateur d\'indexation 3, :cpp:`++a -\-a`, Opérateurs de pré incrémentation/décrémentation ,:cpp:`-a`, Opérateur moins unaire , :cpp:`!` , Opérateur NON logique 5, :cpp:`a\*b a/b a%b` , Opérateurs arithmétiques : multiplication division modulo 6, :cpp:`a+b a-b`, Opérateurs arithmétiques : addition et soustraction 9, :cpp:`< <= > >=`, Opérateurs de comparaison 10, :cpp:`== !=`, Opérateurs d'égalité et de différence 14, :cpp:`&&`, Opérateur ET logique 15, :cpp:`||`, Opérateur OU logique 16, :cpp:`= += -= \*= /=`, Opérateurs d'affectations Pour terminer ============= Opérateurs d'affectation ------------------------ Parmi les `opérateurs d'affectation `_, on trouve :cpp:`+=`, :cpp:`-=`, :cpp:`\*=` ou encore :cpp:`/=`. Ces opérateurs permettent une écriture plus compacte et plus lisible du code. Nous vous conseillons donc de les utiliser. .. quiz:: evalAffectations :title: Affectations Sachant que la variable :cpp:`a` vaut :cpp:`5`, donnez sa valeur après l’évaluation de chaque affectation : .. csv-table:: :header: Expression, Valeur :widths: 10, 10 :delim: ! :cpp:`a += 3` ! :quiz:`{"type":"FB","answer":"8"}` :cpp:`a -= 2` ! :quiz:`{"type":"FB","answer":"3"}` :cpp:`a \*= 2+1` ! :quiz:`{"type":"FB","answer":"15"}` Opérateurs de pré/post incrémentation ------------------------------------- Une variable est dite **incrémentée** lorsque sa valeur est augmentée de 1. Nous présentons : - l'opérateur :cpp:`++x` appelé opérateur de **pré-incrémentation** (:cppterm:`pre-increment operator`) - l'opérateur :cpp:`x++` appelé opérateur de **post-incrémentation** (:cppterm:`post-increment operator`) Ces deux opérateurs :cpp:`++` s'appliquent uniquement sur des variables. L'écriture :cpp:`4++` est une erreur. Ces deux opérateurs ont pour objectif d'incrémenter la variable :cpp:`x`, ils se distinguent uniquement par le résultat retourné : * :cpp:`++x` retourne la variable :cpp:`x` dont la valeur a été incrémentée * :cpp:`x++` retourne la valeur initiale de :cpp:`x`, avant son incrémentation Dans la pratique, vous pouvez utiliser uniquement l'écriture :cpp:`x++`. Cependant, en lisant des exemples, vous trouverez les deux écritures. .. quiz:: evalPosPreIncr :title: Opérateurs de pré/post incrémentation Sachant que la variable :cpp:`a` vaut :cpp:`5` avant l'exécution de chaque ligne, donnez l'affichage ainsi que la valeur de :cpp:`a` après l'exécution : .. csv-table:: :header: Code, Affichage, Valeur de *a* après l'exécution :widths: 10, 10 , 10 :delim: ! :cpp:`std::cout << a++;` ! :quiz:`{"type":"FB","answer":"5"}` ! :quiz:`{"type":"FB","answer":"6"}` :cpp:`std::cout << a-\-;` ! :quiz:`{"type":"FB","answer":"5"}` ! :quiz:`{"type":"FB","answer":"4"}` :cpp:`std::cout << -\-a;` ! :quiz:`{"type":"FB","answer":"4"}` ! :quiz:`{"type":"FB","answer":"4"}` :cpp:`std::cout << ++a;` ! :quiz:`{"type":"FB","answer":"6"}` ! :quiz:`{"type":"FB","answer":"6"}` .. note:: 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 :cpp:`++++a` est donc possible bien que peu lisible. Pour l'opérateur de post-incrémentation, le type de retour étant une valeur, cela ne permet pas de chaîner cet opérateur : l'écriture :cpp:`a++++` est incorrecte. Respirez et relisez ce passage :)