Menu

Operatori in C++: aritmetici, di confronto, logici e altri

Impara gli operatori in C++: aritmetici, di confronto, logici, di assegnazione e bit a bit, più le trappole su divisione intera, precedenza e valutazione a cortocircuito.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Cosa fanno gli operatori

Un operatore è un simbolo che esegue un'azione su uno o più valori, chiamati operandi. Ne hai già usato uno: il = che lega un valore a una variabile. C++ offre un ricco insieme di operatori per matematica, confronti, logica e manipolazione di bit, e qualche spigolo vivo che mette in difficoltà chi inizia.

Nella pagina precedente hai visto come const blocca un valore. Gli operatori sono il modo in cui calcoli i valori che memorizzi, costanti o no. Vediamo le famiglie che userai ogni giorno.

Operatori aritmetici

I cinque operatori aritmetici sono +, -, *, / e % (modulo, il resto di una divisione):

La grande trappola si nasconde in quel quoziente. 17 / 5 stampa 3, non 3.4. Quando entrambi gli operandi sono interi, / esegue la divisione intera e butta via la parte frazionaria: tronca verso lo zero, non arrotonda. Se vuoi una vera frazione, almeno un operando deve essere in virgola mobile:

L'operatore % funziona solo con gli interi. Usare % su un double è un errore di compilazione: per il resto in virgola mobile usa std::fmod da <cmath>.

Assegnazione e operatori composti

Un singolo = assegna, non confronta. C++ ti offre forme composte che uniscono un'operazione e un'assegnazione, così non ripeti il nome della variabile:

Un errore classico e doloroso è scrivere = dove intendevi == dentro una condizione. if (x = 0) assegna 0 a x e poi valuta il risultato (che è falso), invece di confrontare. I compilatori moderni lo segnalano con un avviso quando attivi gli avvisi: tieni attivo -Wall e prendi sul serio l'avviso.

Operatori di confronto

Gli operatori di confronto pongono una domanda sì/no e producono un bool (true o false):

Per default cout stampa un bool come 1 o 0. Invia boolalpha allo stream una volta e passa alle parole true/false per il resto di quello stream.

Una trappola sottile: non concatenare confronti come 1 < x < 10. Viene interpretato come (1 < x) < 10: il primo confronto produce un bool (0 o 1), che viene poi confrontato con 10, quindi il tutto è quasi sempre true. Scrivi invece 1 < x && x < 10.

Operatori logici e cortocircuito

&& (e), || (o) e ! (non) combinano espressioni booleane. I primi due sono a cortocircuito: la valutazione si ferma non appena il risultato è noto.

Né check("A") né check("B") vengono mai eseguiti: questo è il cortocircuito. Non è solo un'ottimizzazione, è uno strumento. Puoi scrivere in sicurezza if (ptr != nullptr && ptr->ready) perché la parte ptr->ready viene raggiunta solo quando ptr non è nullo, evitando di dereferenziare un puntatore non valido.

Incremento e decremento

++ aggiunge uno; -- sottrae uno. Ognuno ha una forma prefissa e una postfissa, e la differenza conta quando usi il risultato:

Quando vuoi solo l'effetto collaterale (per esempio in un ciclo for), preferisci ++i. Per un semplice int è identico, ma per tipi più pesanti come gli iteratori il post-incremento deve prima copiare il vecchio valore, ed è lavoro sprecato.

Un altro avvertimento: non modificare la stessa variabile due volte in una sola espressione, come i = i++ + 1; o arr[i] = i++;. L'ordine di quegli aggiornamenti non è specificato e il risultato è undefined behavior. Limita ogni variabile a una sola modifica per istruzione.

Operatori bit a bit e precedenza

Per il lavoro a basso livello ci sono gli operatori bit a bit: & (and), | (or), ^ (xor), ~ (not) e gli shift << e >>.

Attenzione: << e >> sono anche gli operatori di stream di cout. Dentro una riga con cout di solito servono le parentesi attorno a uno shift di bit, altrimenti il compilatore lo legge come un inserimento nello stream.

Infine, la precedenza decide cosa si lega per primo quando mescoli gli operatori. * e / legano più forte di + e -, proprio come in matematica, quindi 2 + 3 * 4 vale 14. Il confronto lega meno dell'aritmetica, e i logici &&/|| ancora meno. Nel dubbio, non imparare a memoria l'intera tabella: aggiungi le parentesi. (a + b) * c è più chiaro che contare sul fatto che chi legge ricordi le regole.

Prossimo passo: la conversione di tipo

Hai visto sopra che (double)a / b ha forzato un intero in una divisione in virgola mobile. Quello è un cast: convertire deliberatamente un valore da un tipo a un altro. Nella prossima pagina vedremo gli strumenti di conversione di C++, dalle promozioni implicite a static_cast, e quando ciascuno è sicuro.

Domande frequenti

Quali sono gli operatori in C++?

C++ raggruppa gli operatori in aritmetici (+ - * / %), di confronto (== != < > <= >=), logici (&& || !), di assegnazione (= += -= ...), di incremento e decremento (++ --) e bit a bit (& | ^ ~ << >>). Ci sono anche il ternario ?: e pochi altri come sizeof.

Perché 5 / 2 fa 2 in C++?

Perché entrambi gli operandi sono int, quindi / esegue una divisione intera e la parte frazionaria viene scartata, non arrotondata. Per ottenere 2.5, rendi almeno un operando un valore in virgola mobile: 5.0 / 2 o 5 / 2.0.

Qual è la differenza tra ++i e i++ in C++?

Entrambi aggiungono 1 a i. ++i (pre-incremento) incrementa prima e restituisce il nuovo valore; i++ (post-incremento) restituisce il vecchio valore e poi incrementa. Quando ti interessa solo l'effetto collaterale, preferisci ++i.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA