2011-10-11 13 views

risposta

19

Nella maggior parte dei casi (in C almeno), lo sizeof(*x) non valuta affatto lo *x. Lo standard C99 ha questo da dire in 6.5.3.4 The sizeof operator, parte /2 (mio grassetto):

L'operatore sizeof cede la dimensione (in byte) del suo operando, che può essere un'espressione o il nome parentesi di un tipo. La dimensione è determinata dal tipo dell'operando. Il risultato è un numero intero. Se il tipo dell'operando è un tipo di array di lunghezza variabile, viene valutato l'operando; altrimenti, l'operando non viene valutato e il risultato è una costante intera.

Quindi, per tutti i non VLA, non avviene alcun dereferenziamento. Se il tipo di *xè un VLA, questa è considerata una fase di esecuzione sizeof, qualcosa che deve essere elaborato mentre il codice è in esecuzione - tutti gli altri possono essere calcolati in fase di compilazione.

C++ ha regole leggermente diverse, come mostrato in 5.3.3. Sizeof, parte /1:

L'operatore sizeof restituisce il numero di byte nella rappresentazione dell'oggetto del suo operando. L'operando è un'espressione, che è un operando non valutato (clausola 5) o un id-tipo parentesi.

5. Expressions definisce il termine "operando non valutata" in parte /8:

In alcuni contesti, appaiono operandi non valutate. Un operando non valutato non viene valutato.

(forse una delle frasi inutili e ridondanti che ho letto per un po ', ma non so cosa stesse passando per la mente degli ISO quando lo hanno scritto).

+1

Per completezza, in C++ (che non ha VLAs) l'espressione non viene mai valutata: C++ 11, 5.3.3 dice "L'operando è o un'espressione, che è un operando non valutato (Clausola 5), ​​o una parentesi tipo-id ". –

+0

Cheers, @Mike, l'hanno incorporato nella risposta per completezza. – paxdiablo

10

No. sizeof è un operatore e funziona sui tipi, non sul valore effettivo (che non viene valutato).

Per ricordarti che si tratta di un operatore, ti suggerisco di abituarti ad omettere le parentesi dove pratico.

int* ptr = 0; 
size_t size = sizeof *ptr; 
size = sizeof (int); /* brackets still required when naming a type */ 
+2

Questo, e l'espressione non viene mai valutata, viene analizzata solo per determinare il tipo di risultato. Per quello che vale, penso che '& * ptr' sia anche legale. –

+0

@ChrisLutz: Grazie, ho inserito il "non valutato" nella mia risposta. –

+0

Perché è importante ricordare che si tratta di un operatore? – UncleBens

3

sizeof (* ptr) è uguale a sizeof (int) in questo caso.

+0

Sì, ma perché? Questa risposta manca un po 'di qualcosa per darla in piedi ... –

+0

ptr è un puntatore a un numero intero. * ptr è un numero intero. sizeof (* ptr) è sizeof (un intero). – EricS

3

sizeof e decltype non valutano i loro operandi, solo i tipi di calcolo.

4

La risposta potrebbe essere diversa per C, dove sizeof non è necessariamente un costrutto in fase di compilazione, ma in C++ l'espressione fornita a sizeof non viene mai valutata. In quanto tale, non c'è mai la possibilità che un comportamento indefinito si esibisca. Con una logica simile, puoi anche "chiamare" funzioni che non sono mai definite [perché la funzione non viene mai effettivamente chiamata, nessuna definizione è necessaria], un fatto che viene spesso utilizzato nelle regole di SFINAE.

Problemi correlati