2011-01-09 19 views
7

Si consideri il seguente codice:intesa C dimensioni ++ struct

struct CExample { 
    int a; 
}    

int main(int argc, char* argv[]) { 

    CExample ce1; 
    CExample ce2; 

    cout << "Size:" << sizeof(ce1) << " Address: " << &ce1 << endl; 
    cout << "Size:" << sizeof(ce2) << " Address: " << &ce2 << endl; 

    CExample ceArr[2]; 
    cout << "Size:" << sizeof(ceArr[0])<< " Address: "<< &ceArr[0] <<endl; 
    cout << "Size:" << sizeof(ceArr[1])<< " Address: "<< &ceArr[1] <<endl; 

    return 0; 
} 

Esempio di stampa:
CE1: Size = 4, Indirizzo: 0039FAA0
CE2: Size = 4, Indirizzo: 0039FA94
ceArr [0] : Dimensione = 4, Indirizzo: 0039FA84
ceArr [1]: Dimensione = 4, Indirizzo: 0039FA88

Con il codice è un 12-byte tra gli indirizzi dei primi due oggetti (CE1 e CE2) ma ci è solo una differenza di 4 byte ween gli oggetti nella matrice.

Ho pensato che l'allineamento dei dati avrebbe avuto qualcosa a che fare con il problema, ma sono ancora perplesso. Qualche idea su cosa sta succedendo qui?

+2

Qual è l'uscita di cui sopra? Mente postare anche nel codice? –

risposta

15

Poiché gli oggetti in una matrice devono essere contigui. Gli oggetti dichiarati consecutivamente nello stack (nel codice sorgente, non nella macchina) non sono [richiesti per essere contigui], sebbene possano esserlo.

+1

Beh, possono ** essere **, ma non sono ** richiesti ** per essere. –

+0

@Billy Questo è quello che ho detto. –

+0

Scusa ... ho letto male. La seconda frase, letta da sola, sembra dire che non sono mai contigue. Spiacente :( –

6

Lo standard non dice nulla a riguardo. Il compilatore è libero di inserire qualsiasi padding che vuole tra gli oggetti.

(Se dovessi tirare a indovinare, direi che il compilatore implementa qualche forma di protezione dello stack/canarino in modalità debug (e che si sta compilando in modalità debug))

+0

Possibile è riservare spazio di oggetti temporanei, (o forse c'è un uovo di Pasqua loro? –

+0

Sì hai ragione! Ho provato a compilare in modalità di rilascio e ha funzionato come mi aspettavo! – kiokko89

0

La ragione è che, sulla la maggior parte delle architetture, carichi non allineati sono lenti. Vedere la voce di Wikipedia su data structure alignment per una buona spiegazione. Il compilatore posiziona ciascuna delle tue strutture di dati all'inizio di una parola di dati. Tuttavia, negli array, gli oggetti vengono collocati in modo contiguo in memoria (come richiesto dallo standard C++).

+2

Non conosco architetture che richiedano allineamento su confini di 12 byte. Sei a conoscenza di qualsiasi? –

+0

No. L'OP non aveva pubblicato l'output (IIRC), il che dimostra che non si tratta di un problema di allineamento. significa 12 byte = 16 byte meno i 4 byte dell'oggetto originale.Quando l'ho compilato sul mio Mac, ho ottenuto la differenza di 16 byte prevista. @ kiokko89 - non è importante, ma quale compilatore/piattaforma stai usando? – EmeryBerger

+0

sto usando il compilatore di Visual Studio con una macchina x64 (scusatemi ancora per il mio pessimo inglese) – kiokko89

1

Il compilatore non utilizza solo lo stack per conservare le variabili locali, ma lo utilizza anche per il passaggio di argomenti e parte dell'overhead causato da std::cout. Questo è probabilmente lo spazio extra tra le tue variabili.

Se invece fate le vostre variabili static, come questo:

static CExample ce; 
static CExample ce2; 

static CExample ceArr[2]; 

... le variabili verranno messi in memoria BSS invece, e l'allineamento sarà più probabile essere quello che vi aspettate.

Il motivo per cui sono confezionati gli array, e gli elementi individuali non sono, è chiarito da altre risposte ...