Operatore Virgola in C++
- L'operatore
sizeof
restituisce la dimensione, in byte, di un'espressione o di un nome di tipo. sizeof
è associativo a destra e restituisce un'espressione costante di tiposize_t
.sizeof
non valuta il suo operando, rendendolo sicuro da usare con puntatori non validi.- La dimensione restituita da
sizeof
dipende dal tipo coinvolto, comechar
, puntatori, array e tipi di classe. sizeof
di un array restituisce la dimensione totale dell'array, non convertendolo in un puntatore.- Il risultato di
sizeof
può essere utilizzato per specificare la dimensione di un array.
Operatore Virgola
L'operatore virgola prende due operandi, che valuta da sinistra a destra. Come l'AND logico e l'OR logico e l'operatore condizionale, l'operatore virgola garantisce l'ordine in cui i suoi operandi vengono valutati.
L'espressione a sinistra viene valutata e il suo risultato viene scartato. Il risultato di un'espressione virgola è il valore del suo operando destro. Il risultato è un l-value se l'operando destro è un l-value.
Un uso comune per l'operatore virgola è in un ciclo for
:
vector<int>::size_type cnt = ivec.size();
// assegna valori da size ... 1 agli elementi in ivec
for(vector<int>::size_type ix = 0;
ix != ivec.size(); ++ix, --cnt)
ivec[ix] = cnt;
Questo ciclo incrementa ix
e decrementa cnt
nell'espressione nell'intestazione del for
. Sia ix
che cnt
vengono modificati ad ogni iterazione del ciclo. Finché il test di ix
ha successo, impostiamo l'elemento corrente al valore corrente di cnt
.
Esercizi
-
Il programma di sopra ha usato gli operatori di incremento e decremento prefissi. Spiega perché abbiamo usato il prefisso e non il postfisso. Quali cambiamenti dovrebbero essere fatti per usare le versioni postfisse? Riscrivi il programma usando operatori postfissi.
Soluzione:
Per capire meglio come funziona il programma di sopra, possiamo riscriverlo usando un ciclo
while
:vector<int>::size_type cnt = ivec.size(); // assegna valori da size ... 1 agli elementi in ivec // Inizializzazione vector<int>::size_type ix = 0; while(ix != ivec.size()) { ivec[ix] = cnt; ++ix, --cnt; }
Come si può osservare, in questo caso l'uso dell'operatore prefisso è completamente indifferente. Infatti, possiamo riscrivere l'ultima riga del ciclo
while
come segue:ix++, cnt--;
In entrambi i casi, il risultato dell'operatore virgola è il valore di
cnt--
o--cnt
, che viene scartato. Quindi, in questo caso, non c'è differenza tra l'uso del prefisso o del postfisso. Tuttavia, l'uso del prefisso è generalmente preferito quando non è necessario il valore precedente, poiché può essere più efficiente per i tipi di dati complessi. -
Spiega il seguente ciclo.
constexpr int size = 5; int ia[size] = {1,2,3,4,5}; for (int *ptr = ia, ix = 0; ix != size && ptr != ia+size; ++ix, ++ptr) { /* *...* */ }
Soluzione:
Questo ciclo
for
utilizza due variabili di controllo: un puntatoreptr
che inizia all'inizio dell'arrayia
, e un indiceix
che inizia da 0. La condizione del ciclo verifica cheix
sia diverso dasize
(5) e cheptr
non abbia raggiunto la fine dell'array (ia + size
). Ad ogni iterazione, entrambiix
eptr
vengono incrementati. Questo permette di iterare attraverso l'arrayia
, conptr
che punta all'elemento corrente eix
che tiene traccia dell'indice corrente. -
Usando la tabella degli operatori spiega cosa fa la seguente espressione:
valore ? ++x, ++y : --x, --y
Soluzione:
La precedenza degli operatori determina l'ordine in cui le operazioni vengono eseguite in un'espressione. In questo caso, l'operatore condizionale
? :
ha una precedenza più alta rispetto all'operatore virgola,
. Quindi, l'espressione viene valutata come:valore ? (++x, ++y) : (--x, --y)
Se
valore
è vero, vengono eseguiti++x
e++y
, incrementando entrambix
ey
e viene restituito il valore di++y
. Sevalore
è falso, vengono eseguiti--x
e--y
, decrementando entrambix
ey
e viene restituito il valore di--y
. In entrambi i casi, l'operatore virgola consente di eseguire due operazioni in sequenza, ma solo il risultato dell'ultima operazione viene restituito come risultato dell'intera espressione condizionale.