Résumé
Une expression C++ peut faire deux choses distinctes : donner une valeur et changer l’état du programme. x + 1 donne seulement une valeur ; x = 7 donne une valeur et, de plus, change x ; x++ donne la valeur que x avait et laisse dans x une autre valeur. Cette leçon étudie cette différence entre la valeur et l’effet d’une expression : l’affectation comme expression, l’affectation composée, l’incrémentation et la décrémentation sous leurs formes préfixe et suffixe, et l’ordre dans lequel s’évaluent les parties d’une expression, que la norme ne fixe qu’en partie. Il s’ensuit la question qui ordonne le reste de la leçon : ce que la norme promet au sujet d’un programme. La réponse est un catalogue de quatre degrés, du comportement défini au comportement indéfini, qui réunit tous les cas vus jusqu’ici et dit, pour chacun, ce qui le détecte (le compilateur, le détecteur, la bibliothèque) et ce que rien ne détecte.
Objectifs d’apprentissage
- Distinguer la valeur d’une expression de son effet de bord dans les affectations, les incrémentations et les appels.
- Prédire le résultat de
x++et de++xutilisés comme valeur, et suivre à la main un programme comportant des affectations composées. - Reconnaître les expressions qui modifient deux fois une variable, ou qui la lisent et la modifient, sans un ordre fixé par la norme, et les réécrire en instructions séparées.
- Classer une construction comme définie, définie par l’implémentation, non spécifiée ou indéfinie, avec un exemple de chaque catégorie.
- Dire, pour chaque comportement indéfini du catalogue, si le compilateur le signale, si le détecteur ou la bibliothèque l’arrêtent, ou si rien ne le détecte.
La valeur et l’effet
La leçon Arithmétique a étudié l’expression comme un arbre qui se réduit à une valeur : 2 + 3 * 4 vaut 14, et la calculer ne change rien hors de l’expression elle-même. La leçon Relations et logique a fait de même avec les conditions, dont la valeur est true ou false. Or il existe des expressions qui, en plus de donner une valeur, laissent une trace dans l’état du programme : elles changent la valeur d’une variable, écrivent à l’écran ou lisent depuis l’entrée. Cette trace s’appelle un effet de bord, ou simplement un effet, et les mots « de bord » ne veulent pas dire qu’il importe moins : dans x = 7 l’effet, que x vaille désormais 7, est justement ce que l’on cherche.
S’il en est ainsi, toute expression doit se lire avec deux questions : ce qu’elle donne et ce qu’elle fait. Trois exemples fixent la distinction. count + 1 donne le successeur de count et ne fait rien : count conserve sa valeur. count = 9 donne 9 et fait que count vaille 9. std::println("bonjour") est aussi une expression, un appel de fonction, et ce qui compte en elle est son effet : écrire une ligne. Les fonctions que l’on écrit soi-même seront étudiées dans la leçon Fonctions, et la distinction y reparaîtra : une fonction qui ne fait que calculer son résultat est plus facile à comprendre et à tester qu’une fonction qui, en plus, change quelque chose hors d’elle.
Une instruction comme count + 1; est du C++ valide : la valeur est calculée puis écartée, de sorte qu’elle ne sert à rien, et GCC le signale avec -Wunused-value. Une instruction-expression n’a de sens que par son effet. Il s’ensuit que les expressions à effet sont celles qui font avancer le programme, et aussi celles qui exigent de la prudence, car l’effet se produit à un certain moment, et ce moment n’est pas toujours celui que le lecteur suppose.
Chargement du contenu…