Aller au contenu
Topos Uranos

Résumé

Cette leçon clôt la troisième unité du cours, consacrée aux expressions et à leurs opérateurs. Elle reconstruit la chaîne des concepts qui va de l’opérateur arithmétique à la fonction de bibliothèque, en passant par l’arbre de l’expression et le type de chaque nœud, les conditions et leur algèbre, le court-circuit, l’effet de bord et l’ordre d’évaluation, et les bits ; elle sépare ce qui en vaut dans tout langage de ce qui est propre à C++ ; elle réunit le comportement indéfini de l’unité, avec ce que détecte le compilateur, ce que détecte le détecteur et ce que personne ne détecte ; elle reprend dans son évaluation de sortie les savoir-faire de l’évaluation d’entrée ; et elle se termine par six défis qui combinent l’unité entière.

Objectifs d’apprentissage

  1. Prévoir la valeur, le type et l’effet de toute expression du cours, à partir de son arbre et des conversions à chaque nœud.
  2. Écrire et nier des conditions composées, et utiliser le court-circuit pour protéger une opération qui autrement n’aurait pas de sens.
  3. Reconnaître les expressions qui n’ont pas de sens (le catalogue du comportement indéfini de l’unité), dire quel outil détecte chacune et les réécrire sans lui.
  4. Choisir entre l’arithmétique, les opérateurs bit à bit et la bibliothèque mathématique pour un calcul donné, et justifier ce choix.
  5. Séparer, dans ce qui a été appris dans l’unité, ce qui vaut dans tout langage de ce qui est propre à C++.

L’acquis de l’unité

L’unité s’est proposé d’enseigner à construire des expressions dont la valeur peut être prévue avec certitude : quelle opération se fait d’abord, de quel type est le résultat, quels effets de bord elle a et quelles expressions n’ont pas de sens. Le but a été atteint en s’appuyant seulement sur ce que l’introduction a déclaré tenir pour acquis : les types de l’unité 2, leurs plages et leurs conversions. Le programme des six questions par lequel l’introduction a posé le problème peut maintenant être lu comme le lit le compilateur, et corrigé expression par expression.

Arithmétique

La leçon Arithmétique a établi le comportement exact des cinq opérateurs arithmétiques. La division entière tronque vers zéro et vérifie l’identité (a / b) * b + a % b == a chaque fois que le quotient a un sens, de sorte que le reste, quand il n’est pas nul, porte le signe du dividende ; d’où -7 / 2 vaut −3-3 et -7 % 2 vaut −1-1, et l’imparité se teste avec n % 2 != 0. Elle l’a reliée au reste euclidien, ((a % b) + b) % b pour b>0b > 0, et a utilisé les deux pour décomposer des quantités. Elle a appris à dessiner l’arbre d’une expression selon la priorité et l’associativité, et à décider du type à chaque nœud par les conversions arithmétiques usuelles. Elle s’est close sur les quotients sans sens (la division entière par zéro et le plus petit entier divisé par −1-1) et sur le dépassement d’un résultat intermédiaire, qui suffit pour le comportement indéfini même si le résultat final tient.

Relations et logique

La leçon Relations et logique a enseigné qu’une condition est une expression de type bool, avec sa place dans l’arbre : les relations sont moins prioritaires que l’arithmétique, && plus que ||, et ! plus que toutes. Elle a appris à traduire des énoncés en conditions et à reconnaître celles qui compilent avec un autre sens, comme 1 < x < 5 et day == 6 || 7. Elle a montré que && et || n’évaluent leur second opérande que si le premier ne décide pas, et que ce court-circuit permet de protéger une opération par une garde placée à sa gauche. Elle s’est terminée par les lois de De Morgan, qui nient une condition composée, et par leur limite : avec une valeur non numérique, !(a < b) n’équivaut pas à a >= b.

Affectation, effets de bord et comportement indéfini

La leçon Affectation, effets de bord et comportement indéfini a distingué la valeur d’une expression de son effet : l’affectation est une expression qui vaut ce qui est affecté et qui change une variable, et x++ vaut l’ancienne valeur tandis que ++x vaut la nouvelle. Elle a montré que l’arbre d’une expression ne fixe pas l’ordre dans lequel ses branches sont calculées, de sorte que deux effets sur une même variable, ou un effet et une lecture, sans ordre entre eux, laissent l’expression sans sens, et elle a précisé ce que C++17 a ordonné et ce qu’il a laissé non spécifié. Elle a réuni le catalogue des quatre degrés (défini, défini par l’implémentation, non spécifié et indéfini), a expliqué que le compilateur raisonne en supposant que le programme n’a pas de comportement indéfini, et a dit, pour chaque cas du catalogue, quel outil le détecte.

Bits et bibliothèque mathématique

La leçon Bits et bibliothèque mathématique a enseigné qu’un entier est aussi une suite de bits : &, | et ^ appliquent un connecteur à chaque colonne, ~ inverse tous les bits, et les décalages multiplient et divisent par des puissances de 2, à condition que la quantité du décalage ne soit pas strictement négative et n’atteigne pas la largeur du type. Avec eux, elle a construit les masques qui testent, allument, éteignent et basculent un bit. Elle a averti que ces opérateurs sont moins prioritaires que les relations, de sorte que x & 1 == 0 ne demande pas ce qu’il semble demander, et que ^ n’est pas la puissance. Elle s’est close sur la bibliothèque : <cmath>, <numbers>, <numeric> et <bit> donnent des calculs corrects et éprouvés, avec leurs propres préconditions, comme celle de la valeur absolue, qui n’existe pas pour le plus petit entier.