Queste sono varie forme del cosiddetto "struct hack", discusso nella domanda 2.6 dello comp.lang.c FAQ.
La definizione di una matrice di dimensione 0 è in realtà illegale in C, ed è stata almeno dallo standard ANSI del 1989. Alcuni compilatori lo consentono come un'estensione, ma basarsi su ciò porta a un codice non portatile.
Un modo più portabile per implementare questo è quello di utilizzare un array di lunghezza 1, ad esempio:
struct foo {
size_t len;
char str[1];
};
Si può allocare più sizeof (struct foo)
byte, utilizzando len
per tenere traccia della dimensione allocata, e poi accedere a str[N]
per ottenere l'ennesimo elemento dell'array. Poiché i compilatori C in genere non eseguono il controllo dei limiti di array, questo in genere "funziona". Ma, in senso stretto, il comportamento non è definito.
La norma ISO 1999 ha aggiunto una funzione denominata "membri di matrice flessibili", destinato a sostituire questo uso:
struct foo {
size_t len;
char str[];
};
si può trattare con questi nello stesso modo come il più vecchio trucco struct, ma il comportamento è ben definito. Ma devi fare tutta la contabilità da solo; sizeof (struct foo)
ancora non include la dimensione della matrice, per esempio.
È possibile, ovviamente, utilizzare un puntatore invece:
struct bar {
size_t len;
char *ptr;
};
e questo è un buon approccio alla perfezione, ma ha una semantica diversa. Il vantaggio principale di "struct hack", o di membri di array flessibili, è che l'array è allocato in modo contiguo con il resto della struttura, e si può copiare l'array insieme alla struttura usando memcpy
(purché l'obiettivo sia stato adeguatamente assegnato). Con un puntatore, l'array viene assegnato separatamente, il che può essere o non essere esattamente quello che vuoi.
Si prega di fornire un esempio. – Arafangion
Precisazioni relative alle strutture. Ci sono tre casi, 'lastMemberOfArray []' in C90, 'lastMemberOfArray []' in C99 e 'lastMemberOfArray [0]' in GNU goo non standard. Nel caso C90, si tratta di un attacco sporco basato su un comportamento indefinito. È possibile che si verifichino problemi se alla fine della struttura sono presenti byte di riempimento della struttura. C99 ha risolto questo problema e ha creato un tipo chiamato _flessibile membro dell'array_, che funziona allo stesso modo ma con un comportamento ben definito. Infine, GNU non standard consente array di dimensioni zero per lo stesso scopo. Compila come standard con '-std = c99 -pedantic-errors' e' [0] 'non verrà compilato. – Lundin
@ Il primo esempio di Lundin avrebbe dovuto essere "' lastMemberOfArray [1] 'in C90". Errore di battitura semplice, aggiungendolo solo a beneficio di chi non ricorda. –