2013-08-17 17 views
5

Ho una struttura definita come:Perché offsetof (membro) è uguale a sizeof (struct)?

struct smth 
{ 
    char a; 
    int b[]; 
}; 

Quando chiamo sizeof e offsetof su questo struct:

cout << sizeof(struct smth) << endl; 
cout << offsetof(struct smth, b) << endl; 

uscita è:

4 
4 

Come mai quando la dimensione del stuct è 4 e char usa 1 byte, l'offset dell'array int è 4? Perché c'è qualche tipo di padding? Inoltre, perché l'array int non occupa affatto spazio?

+1

Significa "offsetof (struct smth, b)", giusto? –

+0

@CarlNorum Sì, lo so. Modificato. – bugra

+2

C o C++? Sono diversi. –

risposta

8

Come mai quando la dimensione della stuttura è 4 e il char utilizza 1 byte, l'offset dell'array int è 4? Perché c'è una sorta di imbottitura?

C'è un riempimento perché lo standard C lo consente; il compilatore allinea spesso le variabili per migliorare le prestazioni.

Inoltre, perché la seconda variabile non occupa affatto lo spazio (che sembra il caso)?

È un membro di array flessibile C99: è questo il punto. L'idea è di destinare la struttura qualcosa di simile:

struct smth *s = malloc(sizeof *s + 10 * sizeof s->b[0]); 

E poi si sarebbe avere una struttura che opera come se fosse b un array di 10 elementi.

+0

Che tipo di miglioramenti delle prestazioni permetti? Solo curioso. – bugra

+0

@ biox6, alcune istruzioni di caricamento dei processori possono caricare solo parole da indirizzi allineati alle parole. Se hai una parola a un indirizzo non allineato, dovrai caricare ciascun byte separatamente e ricombinarlo. –

+0

L'istruzione di allocazione non considera i vincoli di allineamento. In generale non riuscirà ad allocare la quantità corretta di memoria. Dovresti invece allocare una struttura di dimensioni appropriate usando 'struct smth * s = malloc (offsetof (struct smth, b [10]));'. – IInspectable

3

Poiché le dimensioni dell'organo b è zero, e il compilatore aggiunge spaziatura tra le a e b membri affinché b inizia un confine "parola".

Tuttavia, se ricordo che avere un array flessibile in una struttura del genere è valido solo C, non C++ tranne come estensione del compilatore.

+0

questo è 'int b []' equivalente a int * b? – Light

+2

No, non lo è. 'int * b' renderebbe' sizeof (smth) 'più grande, e lo spazio extra sarebbe dove l'indirizzo di alcune variabili int deve essere memorizzato. Invece, 'int b []' dice che la struttura deve essere allocata dinamicamente con un numero di interi (sconosciuto al momento della compilazione) come un singolo blocco di memoria. – mity

+0

@mity Come assegni un valore (s) alla variabile 'b', puoi darmi la dichiarazione di assegnazione – Light

2

Da OP commenta che la domanda è C++:

struct smth 
{ 
    char a; 
    int b[]; 
}; 

Un array come b[] non è valido in C++. La matrice deve avere dimensioni fisse. Gli array di lunghezza variabile sono validi solo in C99.

Supponendo che il compilatore lo supporti come estensione, l'array b[] ha una dimensione pari a zero, il che rende la struttura contenente solo un membro char. La regola di riempimento in struct funziona, riempire il struct in una parola, che è 4 byte nel computer.