Vai al contenuto
Topos Uranos

Riepilogo

Questa lezione chiude la terza unità del corso, dedicata alle espressioni e ai loro operatori. Ricostruisce la catena dei concetti che va dall’operatore aritmetico alla funzione di libreria, passando per l’albero dell’espressione e il tipo di ciascun nodo, le condizioni e la loro algebra, il cortocircuito, l’effetto collaterale e l’ordine di valutazione, e i bit; separa ciò che di tutto questo vale in qualsiasi linguaggio da ciò che è proprio di C++; riunisce il comportamento indefinito dell’unità, con ciò che rileva il compilatore, ciò che rileva il sanitizer e ciò che non rileva nessuno; ripete nella sua valutazione d’uscita le abilità della valutazione d’ingresso; e termina con sei sfide che combinano l’unità intera.

Obiettivi di apprendimento

  1. Prevedere il valore, il tipo e l’effetto di qualsiasi espressione del corso, a partire dal suo albero e dalle conversioni in ciascun nodo.
  2. Scrivere e negare condizioni composte, e usare il cortocircuito per proteggere un’operazione che altrimenti sarebbe priva di significato.
  3. Riconoscere le espressioni prive di significato (il catalogo del comportamento indefinito dell’unità), dire quale strumento rileva ciascuna e riscriverle senza di esso.
  4. Scegliere tra l’aritmetica, gli operatori bit a bit e la libreria matematica per un calcolo dato, e giustificare la scelta.
  5. Separare, in ciò che si è appreso nell’unità, ciò che vale in qualsiasi linguaggio da ciò che è proprio di C++.

Ciò che l’unità ha ottenuto

L’unità si era proposta di insegnare a costruire espressioni il cui valore si possa prevedere con certezza: quale operazione si fa per prima, di che tipo è il risultato, quali effetti collaterali ha e quali espressioni non hanno significato. Lo scopo è stato raggiunto appoggiandosi solo su ciò che l’introduzione ha dichiarato di dare per scontato: i tipi dell’unità 2, i loro intervalli e le loro conversioni. Il programma delle sei domande con cui l’introduzione ha posto il problema può ora essere letto come lo legge il compilatore, e corretto espressione per espressione.

Aritmetica

La lezione Aritmetica ha stabilito il comportamento esatto dei cinque operatori aritmetici. La divisione intera tronca verso lo zero e soddisfa l’identità (a / b) * b + a % b == a ogni volta che il quoziente ha significato, sicché il resto, quando non è zero, ha il segno del dividendo; per questo -7 / 2 vale −3-3 e -7 % 2 vale −1-1, e la disparità si verifica con n % 2 != 0. L’ha messa in relazione con il resto euclideo, ((a % b) + b) % b per b>0b > 0, e ha usato entrambi per scomporre quantità. Ha insegnato a disegnare l’albero di un’espressione secondo la precedenza e l’associatività, e a decidere il tipo in ciascun nodo con le conversioni aritmetiche usuali. Si è chiusa con i quozienti privi di significato (la divisione intera per zero e il minimo intero diviso per −1-1) e con l’overflow di un risultato intermedio, che basta per il comportamento indefinito anche se il risultato finale ci sta.

Relazioni e logica

La lezione Relazioni e logica ha insegnato che una condizione è un’espressione di tipo bool, con il suo posto nell’albero: le relazioni legano meno dell’aritmetica, && più di ||, e ! più di tutti. Ha insegnato a tradurre enunciati in condizioni e a riconoscere quelle che compilano con un altro significato, come 1 < x < 5 e day == 6 || 7. Ha mostrato che && e || valutano il secondo operando solo se il primo non decide, e che questo cortocircuito permette di proteggere un’operazione con una guardia alla sua sinistra. Si è conclusa con le leggi di De Morgan, che negano una condizione composta, e con il loro limite: con un valore non numerico, !(a < b) non equivale a a >= b.

Assegnamento, effetti collaterali e comportamento indefinito

La lezione Assegnamento, effetti collaterali e comportamento indefinito ha distinto il valore di un’espressione dal suo effetto: l’assegnamento è un’espressione che vale ciò che si assegna e cambia una variabile, e x++ vale il valore precedente mentre ++x vale il nuovo. Ha mostrato che l’albero di un’espressione non fissa l’ordine in cui si calcolano i suoi rami, sicché due effetti su una stessa variabile, o un effetto e una lettura, senza ordine tra loro, lasciano l’espressione priva di significato, e ha precisato ciò che C++17 ha ordinato e ciò che ha lasciato non specificato. Ha riunito il catalogo dei quattro gradi (definito, definito dall’implementazione, non specificato e indefinito), ha spiegato che il compilatore ragiona supponendo che il programma non abbia comportamento indefinito, e ha detto, per ciascun caso del catalogo, quale strumento lo rileva.

Bit e libreria matematica

La lezione Bit e libreria matematica ha insegnato che un intero è anche una successione di bit: &, | e ^ applicano un connettivo a ciascuna colonna, ~ inverte tutti i bit, e gli scorrimenti moltiplicano e dividono per potenze di 2, a condizione che la quantità dello scorrimento non sia negativa né raggiunga la larghezza del tipo. Con essi ha costruito le maschere che consultano, accendono, spengono e invertono un bit. Ha avvertito che questi operatori legano meno delle relazioni, sicché x & 1 == 0 non chiede ciò che sembra, e che ^ non è la potenza. Si è chiusa con la libreria: <cmath>, <numbers>, <numeric> e <bit> danno calcoli corretti e collaudati, con le loro precondizioni, come quella del valore assoluto, che non esiste per il minimo intero.