Sizeof analizza il tipo dell'espressione ad esso assegnata, non valuta l'espressione. Pertanto, è necessario solo accertarsi che le variabili utilizzate nell'espressione siano dichiarate in modo che il compilatore possa dedurne il tipo.
Nell'esempio, st è già dichiarato come pointer-to-struct-retValue. Di conseguenza il compilatore è in grado di dedurre il tipo dell'espressione "* st".
Anche se non sembra che sia già stato dichiarato nel codice, il compilatore si è già preso cura di esso. Tutte le dichiarazioni nel tuo codice vengono spostate all'inizio del blocco in cui si verificano dal compilatore. Supponiamo di scrivere
Un modo per illustrare la conoscenza che è disponibile al compilatore è osservare l'output intermedio che genera. Si consideri questo codice esempio ...
struct retValue {long int a, long int b};
...
printf("Hello World!\n");
struct retValue* st = malloc(sizeof(*st));
Uso gcc come esempio e teh codice in alto nel principale() funzione test.c, esaminiamo produzione intermedia eseguendo ...
gcc -fdump-tree-cfg test.c
il compilatore genera il file test.c.022t.cfg - vedere le cose e vedrete
[ ... removed internal stuff ...]
;; Function main (main)
Merging blocks 2 and 3
main (argc, argv)
{
struct retValue * st;
int D.3097;
void * D.3096;
# BLOCK 2
# PRED: ENTRY (fallthru)
__builtin_puts (&"Hello World!"[0]);
D.3096 = malloc (16);
st = (struct retValue *) D.3096;
D.3097 = 0;
return D.3097;
# SUCC: EXIT
}
Nota come la dichiarazione è stata spostata all'inizio del blocco e l'argomento su malloc è già stato sostituito con il valore effettivo che indica la dimensione del tipo a cui è stata valutata l'espressione. Come sottolineato nei commenti, il fatto che la dichiarazione sia stata spostata in cima al blocco è un dettaglio di implementazione del compilatore. Tuttavia, il fatto che il compilatore sia in grado di farlo e anche di inserire la dimensione corretta nel malloc mostra che il compilatore è stato in grado di dedurre le informazioni necessarie dall'input.
Personalmente preferisco dare il nome del tipo effettivo come parametro a sizeof, ma probabilmente è una questione di stile di codifica in cui direi che la coerenza supera la preferenza personale.
Hai risposto alla tua domanda. sizeof (struct retValue) è corretto –
Spiacente, la domanda non era "È corretto, o cosa è corretto?" era "Perché funziona?" – Blackbinary
Potrebbe aiutare a capire se si modifica la terminologia. Non stai * definendo * una struttura usando malloc, stai * assegnando * una struttura usando malloc. Stai definendo 'st', che è un puntatore (non una struct). Quel puntatore è già definito e disponibile per l'uso nell'espressione initialiser (sul RHS del segno di uguale), semplicemente non ha un valore, quindi la maggior parte degli usi non sarebbe valida. Questo va bene, però, perché sizeof non usa il valore. –