Operatore sizeof 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.
L'Operatore sizeof
L'operatore sizeof
restituisce la dimensione, in byte, di un'espressione o di un nome di tipo. L'operatore è associativo a destra. Il risultato di sizeof
è un'espressione costante di tipo size_t
. L'operatore assume una di due forme:
sizeof (type)
sizeof expr
Nella seconda forma, sizeof
restituisce la dimensione del tipo restituito dall'espressione data. L'operatore sizeof
è insolito nel fatto che non valuta il suo operando:
Libro data, *p;
// dimensione richiesta per contenere un oggetto di tipo Libro
sizeof(Libro);
// dimensione del tipo di data, cioè sizeof(Libro)
sizeof data;
// dimensione di un puntatore
sizeof p;
// dimensione del tipo a cui p punta, cioè sizeof(Libro)
sizeof *p;
// dimensione del tipo del membro costo di Libro
sizeof data.costo;
// modo alternativo per ottenere la dimensione di costo
sizeof Libro::costo;
Il più interessante di questi esempi è sizeof *p
. Primo, poiché sizeof
è associativo a destra e ha la stessa precedenza di *
, questa espressione si raggruppa da destra a sinistra. Cioè, è equivalente a sizeof(*p)
. Secondo, poiché sizeof
non valuta il suo operando, non importa che p
sia un puntatore non valido (cioè, non inizializzato). Dereferenziare un puntatore non valido come operando di sizeof
è sicuro perché il puntatore non viene effettivamente usato. sizeof
non ha bisogno di dereferenziare il puntatore per sapere quale tipo restituirà.
A partire dallo standard C++11, possiamo usare l'operatore di ambito per chiedere la dimensione di un membro di un tipo classe. Normalmente possiamo accedere ai membri di una classe solo attraverso un oggetto di quel tipo. Non abbiamo bisogno di fornire un oggetto, perché sizeof
non ha bisogno di recuperare il membro per conoscere la sua dimensione.
Il risultato dell'applicazione di sizeof
dipende in parte dal tipo coinvolto:
sizeof char
o un'espressione di tipochar
è garantito essere 1.sizeof
di un tipo riferimento restituisce la dimensione di un oggetto del tipo riferito.sizeof
di un puntatore restituisce la dimensione necessaria per contenere un puntatore.sizeof
di un puntatore dereferenziato restituisce la dimensione di un oggetto del tipo a cui il puntatore punta; il puntatore non deve essere valido.sizeof
di un array è la dimensione dell'intero array. È equivalente a prendere ilsizeof
del tipo elemento per il numero di elementi nell'array. Nota chesizeof
non converte l'array in un puntatore.sizeof
di una string o di un vector restituisce solo la dimensione della parte fissa di questi tipi; non restituisce la dimensione usata dagli elementi dell'oggetto.
Poiché sizeof
restituisce la dimensione dell'intero array, possiamo determinare il numero di elementi in un array dividendo la dimensione dell'array per la dimensione dell'elemento:
// sizeof(ia) / sizeof(*ia) restituisce il numero di elementi in ia
constexpr size_t sz = sizeof(ia) / sizeof(*ia);
// ok sizeof restituisce un'espressione costante
int arr2[sz];
Poiché sizeof
restituisce un'espressione costante, possiamo usare il risultato di un'espressione sizeof
per specificare la dimensione di un array.
Esercizi
-
Scrivi un programma che stampa la dimensione di vari tipi primitivi del C++.
Soluzione:
#include <iostream> #include <string> #include <vector> int main() { std::cout << "Dimensione di char: " << sizeof(char) << " byte\n"; std::cout << "Dimensione di int: " << sizeof(int) << " byte\n"; std::cout << "Dimensione di float: " << sizeof(float) << " byte\n"; std::cout << "Dimensione di double: " << sizeof(double) << " byte\n"; std::cout << "Dimensione di bool: " << sizeof(bool) << " byte\n"; std::cout << "Dimensione di long: " << sizeof(long) << " byte\n"; std::cout << "Dimensione di long long: " << sizeof(long long) << " byte\n"; std::cout << "Dimensione di puntatore a int: " << sizeof(int*) << " byte\n"; std::cout << "Dimensione di puntatore a char: " << sizeof(char*) << " byte\n"; std::cout << "Dimensione di string: " << sizeof(std::string) << " byte\n"; std::cout << "Dimensione di vector<int>: " << sizeof(std::vector<int>) << " byte\n"; return 0; }
-
Cosa fanno le seguenti espressioni? Spiega il risultato di ciascuna.
int x[10]; int *p = x; cout << sizeof(x)/sizeof(*x) << endl; cout << sizeof(p)/sizeof(*p) << endl;
Soluzione:
La prima espressione
sizeof(x)/sizeof(*x)
calcola il numero di elementi nell'arrayx
.sizeof(x)
restituisce la dimensione totale dell'array in byte (ad esempio, 40 byte seint
è 4 byte e l'array ha 10 elementi).sizeof(*x)
restituisce la dimensione di un singolo elemento dell'array, che è la dimensione di unint
(ad esempio, 4 byte). Dividendo la dimensione totale dell'array per la dimensione di un singolo elemento otteniamo il numero di elementi nell'array, che è 10.La seconda espressione
sizeof(p)/sizeof(*p)
calcola la dimensione del puntatorep
divisa per la dimensione dell'oggetto a cuip
punta.sizeof(p)
restituisce la dimensione del puntatore stesso (ad esempio, 8 byte su un sistema a 64 bit).sizeof(*p)
restituisce la dimensione di unint
, che è 4 byte. Dividendo la dimensione del puntatore per la dimensione di unint
otteniamo 2 (ad esempio, 8/4 = 2). Questo risultato non ha un significato pratico in questo contesto, poiché non rappresenta il numero di elementi in un array, ma piuttosto il rapporto tra la dimensione del puntatore e la dimensione del tipo a cui punta. -
Utilizzando la tabella degli operatori, metti tra parentesi le seguenti espressioni affinché corrispondano alla valutazione predefinita:
sizeof x + y sizeof p->mem[i] sizeof a < b sizeof f()
Soluzione:
sizeof(x) + y
sizeof((p->mem)[i])
(sizeof(a)) < b
sizeof(f())