2010-12-30 22 views
8

Perché alcuni struct utilizza una singola serie di elementi, come segue:Un elemento di matrice nella struct

typedef struct Bitmapset 
{ 
int nwords; 
uint32 words[1]; 
} Bitmapset; 

per rendere conveniente per l'allocazione dinamica quest'ultimo?

risposta

15

In una parola, sì.

In sostanza, il modo C99 per farlo è con un flexible array member:

uint32 words[]; 

Alcuni compilatori pre-C99 consentono di ottenere via con:

uint32 words[0]; 

Ma il modo per garantire al lavoro in tutti i compilatori è:

uint32 words[1]; 

E poi, non importa come viene dichiarato, è possibile allocare l'arguzia oggetto h:

Bitmapset *allocate(int n) 
{ 
    Bitmapset *p = malloc(offsetof(Bitmapset, words) + n * sizeof(p->words[0])); 
    p->nwords = n; 
    return p; 
} 

Anche se per ottenere i migliori risultati è necessario utilizzare size_t invece di int.

+0

Grazie. Quindi questa allocazione difficile ha un problema per la struttura del riempimento della trama, diciamo se il numero di passaggi n è un numero dispari? – Oxdeadbeef

+0

@Oxdeadbeef - Sì, suppongo. Non li archivierai realmente in una memoria contigua. Se si desidera un array di questi, è preferibile usare 'Bitmapset * a [20] = {NULL};' o 'Bitmapset ** a = malloc (20 * sizeof * a);'. –

+1

La sintassi 'offsetof (Bitmapset, words [n])' è un'estensione (che sembra essere supportata dalla maggior parte dei compilatori). Per una conformità rigorosa, usare 'offsetof (Bitmapset, parole) + n * sizeof (p-> parole [0])'. – Jed

6

Questo di solito consente l'accesso idiomatico a istanze di struct di dimensioni variabili. Considerando il tuo esempio, in fase di esecuzione, si può avere una Bitmapset che viene disposto in memoria come questo:

----------------- 
| nwords | 3 | 
| words[0] | 10 | 
| words[1] | 20 | 
| words[2] | 30 | 
----------------- 

Così si finisce con un numero di runtime-variabile Uint32 "appeso fuori" alla fine della vostra struct, ma accessibile come se fossero definiti in linea nella struttura. Questo è fondamentalmente (ab) usando il fatto che C non esegue il controllo degli array di runtime per permetterti di scrivere codice come:

for (int i = 0; i < myset.nwords; i++) { 
    printf("%d\n", myset.words[i]); 
} 
+0

grazie. ma qual è il vantaggio rispetto all'utilizzo di parole uint32 *? – Oxdeadbeef

+5

Non funzionerebbe allo stesso modo. Se lo facessi, allora le parole [2] direbbero "segui il puntatore situato nel campo" parole "della struct, poi vai avanti di 2 * 8 == 16 byte e accedi alla memoria lì." Dovresti (ad es.,) malloc() una regione di memoria separata per contenere l'array di parole nell'heap e ciò potrebbe influire sulle prestazioni e sulla facilità d'uso. –

Problemi correlati