Linguaggio C: Programmazione (Operatori)

Una volta appreso dell'esistenza delle variabili e delle costanti possiamo iniziare ad operare con esse. A questo scopo il C++ fornisce degli operatori, che nel nostro linguaggio sono un insieme di parole chiave e simboli speciali.  E' importante conoscerli perché essi sono la base del linguaggio C++.

Non è necessario imparare a memoria tutto il contenuto di questa sezione. La maggior parte dei dettagli sono riportati per poterli consultare in seguito qualora se ne abbia bisogno.

Assegnamento (=).

L'operatore di assegnamento serve per assegnare un valore ad una variabile.

a = 5;

assegna il valore intero 5 alla variabile a. La parte alla sinistra dell'operatore = è nota come lvalue

(left value) e la parte destra rvalue (right value).

Lvalue deve essere sempre una variabile mentre la parte destra può essere una costante, una variabile, il risultato di una operazione o una qualsiasi combinazione di essi.

Occorre notare che l'operatore di assegnamento opera sempre da destra verso sinistra e non nel senso inverso.

a = b;

assegna alla variabile a (lvalue) il valore della variabile b (rvalue) indipendentemente dal valore che era precedentemente memorizzato nella variabile a. Possiamo pensare l'lvalue di a come l'indirizzo della zona di memoria riservata per memorizzare il valore di a mentre   l'rvalue di b lo dobbiamo pensare come il valore memorizzato nella zona di memoria riservata per memorizzare il valore di b.  Notiamo inoltre che noi stiamo soltanto assegnando ad a il valore di b e che una modifica successiva di b non cambia il nuovo valore di a.

Ad esempio, il seguente codice (in cui è evidenziata in verde come commento l'evoluzione del contenuto delle variabili):

int a, b;    // a:?  b:?
a = 10;      // a:10 b:?
b = 4;       // a:10 b:4
a = b;       // a:4 b:4
b = 7;       // a:4 b:7

otteniamo alla fine che il valore contenuto in è e quello contenuto in è 7. L'ultima modifica di non ha modificato a, benché appena prima avessimo scritto a = b.

Una caratteristica dell'operatore di assegnamento presente in C++ ma non in altri linguaggi di programmazione è che un assegnamento si può usare come rvalue (o parte di un rvalue ) in un altro assegnamento. Ad esempio:

a = 2 + (b = 5);

è equivalente a:

b = 5;
a = 2 + b;

ossia: prima assegna alla variabile e poi  assegna ad il valore più il risultato del precedente assegnamento a ( 5 appunto),  ottenendo come valore finale di a. Quindi,  anche la seguente espressione è valida in C++:

a = b = c = 5; assegna a tutte e tre le variabili ac.
 

Operatori aritmetici ( +, -, *, /, % )


I cinque operatori aritmetici previsti dal linguaggio sono:

+

somma

-

differenza

*

moltiplicazione

/

divisione

%

modulo (o resto)

Gli operatori di somma, differenza, moltiplicazione e divisione denotano le usuali quattro operazioni numeriche. L'operatore di modulo fornisce il resto della divisione di due numeri interi. Ad esempio, se scriviamo a = 11 % 3;, viene assegnato alla variabile il valore in quanto è proprio il resto che si ottiene dividendo 11 per 3.
 

Operatori di assegnamento composti ( +=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |= )

Gli operatori di assegnamento composti sono una caratteristica del C++   che  contribuisce alla sua fama di essere un linguaggio sintetico.    Essi permettono di modificare il valore di una variabile con una  sola   operazione:

valore += incremento;        è equivalente a valore = valore + incremento;
a -= 5;                                   è equivalente ad a = a - 5;
a /= b;                                   è equivalente ad a = a / b;
prezzo *= numero + 1;       è equivalente a prezzo = prezzo * (numero + 1);

e analogamente per le altre operazioni.
 

Incremento e decremento.

Un altro esempio di sinteticità si ha con gli operatori  di incremento    (++) e di decremento (--). Essi aumentano o diminuiscono  di 1 il valore  di una variabile e sono equivalenti a   += 1   -= 1 rispettivamente. Quindi:

a++;
a += 1;
a = a+1;

fanno la stessa cosa: aumentano di 1 il valore di a.

Questi operatori si possono usare sia come prefissi che come postfissi . Ossia possono essere scritti prima della variabile ( ++a ) o dopo di essa ( a++ ). Benché in espressioni semplici come a++    o ++a gli operatori prefissi e postfissi abbiano lo stesso significato, in altri casi in cui viene utilizzato il risultato dell'operazione nella valutazione di un'altra espressione essi assumono un significato diverso:  Se l'operatore di incremento viene usato come prefisso ( ++a ) il valore della variabile viene incrementato prima della valutazione dell'espressione e quindi l'espressione viene valutata usando il valore incrementato; se l'operatore di incremento viene usato come postfisso    ( a++ ) il valore della variabile viene incrementato dopo la valutazione dell'espressione e quindi l'espressione viene valutata usando il valore non incrementato. Ecco un esempio della differenza tra i due modi di usare l'operatore:

 

Esempio 1

Esempio 2

B = 3;
A = ++B;
// A è 4, B è 4

B = 3;
A = B++;
// A è 3, B è 4

Nel primo esempio, la variabile viene incrementata prima   che il suo valore venga copiato in mentre nel secondo esempio    viene prima copiato in il valore della variabile e poi  viene incrementato il valore della variabile B.
 

Operatori relazionali ( ==, !=, >, <, >=, <= )


Per confrontare i valori di due espressioni si usano gli operatori relazionali.  Come specificato dallo standard ANSI-C++, il risultato di un operatore  relazionale è di tipo bool e può assumere soltanto uno dei due valori booleani true false, a seconda del risultato del confronto.

Ecco la lista degli operatori relazionali del C++:

 

 

==

Uguale

!=

Diverso

> 

Maggiore

< 

Minore 

>=

Maggiore o uguale

<=

Minore o uguale

Ed ecco alcuni esempi:

 

 

(7 == 5)

risultato false .

(5 > 4)

risultato true .

(3 != 2)

risultato true .

(6 >= 6)

risultato true .

(5 < 5)

risultato false .

naturalmente, invece di usare soltanto costanti numeriche possiamo usare qualunque espressioni valida, comprese le variabili. Supponiamo che a=2b=3c=6,

 

 

(a == 5)

risultato false.

(a*b >= c)

risultato true in quanto (2*3 >= 6).

(b+4 > a*c)

risultato false in quanto (3+4 > 2*6).

((b=2) == a)

risultato true.

Attenzione. L'operatore (un solo uguale) è differente dal simbolo == (doppio uguale), il primo è l'operatore di assegnamento (assegna il valore dell'espressione alla sua destra alla variabile alla sua sinistra e ritorna tale valore) mentre il secondo è l'operatore relazionale di uguaglianza che confronta i valori delle due espressioni che stanno ai suoi lati e ritorna il valore booleano true false a seconda che esse abbiano lo stesso valore o valori diversi. Quindi nell'ultima espressione ((b=2) == a), viene dapprima assegnato il valore e quindi tale valore viene confrontato con il valore di a, che è pure 2, e quindi il risultato che si ottiene è il valore true.
 

 

       In molti compilatori  precedenti la pubblicazione dello standard ANSI-C++, come pure in C, gli operatori relazionali non ritornano un valore bool (true false ) ma ritornano  un valore int con che rappresenta   "false" e un valore  diverso  da 0 (in genere 1 ) che rappresenta  "true" . 

Operatori logici ( !, &&, || ).


L'operatore è l'operatore logico di negazione NOT. Esso ha un unico operando (di tipo bool) posto alla sua destra e il suo risultato è l'opposto del valore dell'operando: se l'operando è true esso ritorna false , se l'operando è false esso ritorna true . Ad esempio:

 

 

!(5 == 5)

ritorna false in quanto l'espressione alla sua destra (5 == 5) è true .

!(6 <= 4)

ritorna true in quanto (6 <= 4) è false               .

!true

ritorna false.

!false

ritorna true.

Gli operatori  && || sono gli operatori logici di congiunzione (AND) e disgiunzione (OR). Essi hanno due operandi (di tipo bool), uno alla sinistra ed uno alla destra, e il risultato è quello riportato nella seguente tabella:

 

 

Primo 
operando 
a

Secondo 
operando 
b

Risultato
di
a && b

Risultato
di
a || b

true

true

true

true

true

false

false

true

false

true

false

true

false

false

false

false

Ad esempio:

( (5 == 5) && (3 > 6) ) ritorna false ( true && false ).
( (5 == 5) || (3 > 6) ) ritorna true true || false ) .

Operatore condizionale ( ? ).


L'operatore condizionale valuta una espressione booleana e ritorna un valore diverso a seconda che tale valore sia true oppure false. La sua forma è:

condizione ? risultato1 : risultato2

se condizione è true l'espressione ritorna risultato1, altrimenti ritorna risultato2.

7==5 ? 4 : 3

  ritorna 3 perché 7 non è uguale a 5 .

7==5+2 ? 4 : 3

  ritorna 4 perché 7 è uguale a 5+2 .

5>3 ? a : b

  ritorna a, perché 5 è maggiore di 3    .

a>b ? a : b

  ritorna il maggiore dei due, a o b            .

Operatori bit a bit ( &, |, ^, ~, <<, >> ).


Gli operatori bit a bit operano in parallelo su tutti i bit degli operandi. Essi sono operatori di basso livello a cui corrispondono alcune operazioni assembler. Nella programmazione normale C++ essi non dovrebbero essere usati.

operatore

assembler

                 Descrizione

&

AND

AND bit a bit

|

OR

OR bit a bit

^

XOR

OR esclusivo bit a bit

~

NOT

NOT bit a bit (complemento a uno)

<< 

SHL

Spostamento dei bit (shift) a sinistra

>> 

SHR

Spostamento dei bit (shift) a destra

Operatori espliciti di conversione di tipo (casting)

Gli operatori di conversione servono per convertire valori appartenenti ad un tipo in valori di un altro tipo. Vi sono diversi modi per fare questo in C++. Il vecchi modo (stile C) consiste nel far precedere le espressioni che devono essere convertite dal nome del nuovo tipo racchiuso tra parentesi ():

int i;
float f = 3.14;
i = (int) f;

Il codice precedente converte il numero float 3.14 nel valore intero 3. L'operatore di conversione è rappresentato da (int).  Un modo più consono allo stile C++ è quello di usare la funzione costruttore: far precedere l'espressione da convertire, racchiusa tra parentesi, dal nome del nuovo tipo.

i = int ( f );

Entrambe le forme sono accettate dallo standard ANSI-C++ che inoltre ha aggiunto altri tipi di conversione adatti alla programmazione ad oggetti.

Operatore sizeof()

Questo operatore ha un parametro che può essere sia il nome di un tipo che una espressione. Esso ritorna la memoria, in byte, necessaria a memorizzare un valore di tale tipo o il valore dell'espressione:

a = sizeof (char);

ritorna in perché un valore di tipo char occupa un byte.
Il valore ritornato da è una costante. Esso è quindi determinato a tempo di compilazione (prima dell'esecuzione del programma).
 

Altri operatori

Vedremo nel seguito qualche altro operatore particolare, ad esempio quelli che operano sui puntatori e quelli specifici per la programmazione ad oggetti. Essi verranno trattati nelle rispettive sezioni.

Priorità degli operatori

Quando scriviamo espressioni complesse con molti operatori e operandi possono sorgere dei dubbi sull'ordine in cui gli operatori vengono valutati. Ad esempio, con l'espressione:

a = 5 + 7 % 2

può sorgere il dubbio tra le seguenti due interpretazioni:

a = 5 + (7 % 2) con risultato 6, o
a = (5 + 7) % 2 con risultato 0

L'interpretazione corretta è la prima, quella con risultato 6. Vi è un ordine di priorità prestabilito tra tutti gli operatori (sia aritmetici che non aritmetici). L'ordine di priorità è il seguente:

Priorità

Operatore

Descrizione

Associatività

1

::

scopo

Sinistra

2

() [ ] -> . sizeof

 

Sinistra

3

++ --

incremento/decremento

Destra

~

Complemento a uno (bit a bit)

!

NOT

& *

Referenziazione e Dereferenziazione (puntatori)

(tipo)

Conversione di tipo

+ -

Operatori di segno unario

4

* / %

Operatori aritmetici moltiplicativi

Sinistra

5

+ -

Operatori aritmetici additivi

Sinistra

6

<< >>

Spostamento dei bit 

Sinistra

7

< <= > >=

Operatori relazionali

Sinistra

8

== !=

Operatori relazionali di uguaglianza

Sinistra

9

& ^ |

Operatori bit a bit

Sinistra

10

&& ||

Operatori logici

Sinistra

11

?:

Operatore condizionale

Destra

12

= += -= *= /= %=
>>= <<= &= ^= |=

Assegnamento

Destra

13

,

Operatore virgola, separatore

Sinistra

L'associatività specifica in quale ordine vengono valutati gli operatori con la stessa priorità: partendo da quello più a destra o da quello più a sinistra.

La precedenza degli operatori in una espressione si può modificare o rendere evidente usando le parentesi come nell'esempio seguente:

a = 5 + 7 % 2;

si può scrivere come:

a = 5 + (7 % 2);oppure
a = (5 + 7) % 2;

a seconde di come si vuole venga eseguita l'espressione.

Pertanto, quando si vuole scrivere una espressione complicata e non  si è certi della precedenza degli operatori è bene mettere le parentesi; questo renderà oltretutto più leggibile l'espressione.


Ultime modifiche: lunedì, 9 marzo 2020, 23:05