2011-08-27 8 views
7

Quando stampo le dimensioni di un'unione come questa:Perché le dimensioni della mia unione sono più grandi di quanto mi aspettassi?

union u { 
    char c[5]; 
    int i; 
} un; 

utilizza questo:

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    printf("size of union = %d ",sizeof(un)); 
    return 0; 
} 

ricevo una risposta di 8 utilizzando Visual C++, ma mi aspettavo 5. Perché?

Beh, per lo stesso esempio, ho fatto qualcosa di simile:

int i1 = 0x98761234; 
un.i = i1; 
printf("\n un.c[0] = %x ",un.c[0]); 
printf("\n un.c[1] = %x ",un.c[1]); 
printf("\n un.c[2]= %x ",un.c[2]); 
printf("\n un.c[3] = %x ",un.c[3]); 
printf("\n un.c[4] = %x ",un.c[4]); 
printf("size of union = %d ",sizeof(un)); 

ho ottenuto risultati come

un.c[0] = 34; 
un.c[1] = 12; 
un.c[2] = 76; 
un.c[3] = ffffff98; 

Perché ci sono 6FS a un.c [3]

risposta

11

L'operatore sizeof produce la dimensione di una variabile o tipo, compresi imbottitura necessario elementi separati in un array di tipo tale che tutto è ancora allineata correttamente. Poiché il tuo sindacato ha un membro int, deve essere allineato a 4 byte, quindi la sua dimensione "naturale" viene arrotondata al successivo multiplo di 4 byte.


Il ffffff98 è perché si sta compilando con firmato char. L'utilizzo di %x con un argomento che non è unsigned int causa un comportamento non definito; quello che vedi è a volte chiamato segno-estensione. Il risultato del tuo aliasing è 0x98 reinterpretato come char, ovvero -104. Ciò mantiene il suo valore per essere promosso a int (questo è chiamato lo promozioni di argomento predefinito e il -104 int uno quando alias come unsigned int diventa 0xffffff98.

1

Il compilatore può aggiungere padding ovunque desideri strutture, unioni e classi per accelerare gli accessi alla memoria. Stai vedendo l'effetto di ciò. Per Visual C++, il riempimento è in genere un multiplo della dimensione del tipo di membro più grande. In questo caso, il membro più grande è un int, quindi riempie l'unione con 3 byte non utilizzati per ottenere la dimensione totale 8.

+0

Supponendo integer a 4 byte, il membro più grande è c, che è 5 byte. Il compilatore arrotonda questo fino a 8 aggiungendo padding. Se il sistema utilizza interi a 8 byte, 8 viene utilizzato per le dimensioni dell'unione. –

+0

@Brian Ho cambiato la mia risposta poco prima di commentare "il tipo di membro più grande", per indicare più chiaramente un int. –

+1

Non so, continuo a non pensare che la tua risposta sia chiara o corretta. Tu dici che il membro più grande è un int, ma non lo è. È una matrice di 5 caratteri. Dal 5> 4 si arrotonda al prossimo multiplo della dimensione nativa della parola, il che lo rende 8. –

3

L'allineamento della tua unione deve essere il più grande allineamento di uno qualsiasi dei suoi membri. Questo è 4. Pertanto, la dimensione dell'unione deve essere allineata a quella dimensione. Potrebbe essere stato 5 (come c è il membro più grande del sindacato), ma poiché l'allineamento dell'unione nel suo complesso è 4, la dimensione dell'unione è completata a 8.

Nota che questo è solo per VC++. Lo standard non lo richiede specificamente. Sebbene consenta l'implementazione di tipi di pad in base alle esigenze, come fa VC++. GCC potrebbe fare qualcosa di diverso, e potrebbero esserci degli switch in fase di compilazione che potresti impiegare per cambiare questo comportamento.

0

Grazie per i vostri suggerimenti. Ho provato questo con un sacco di esempi e sembra che la dimensione dell'unione sia equivalente a (dimensione dell'elemento massimo) + padding (a seconda della dimensione del più alto tipo di dati utilizzato).

2

enter image description here compilatore aggiunge pochi byte per l'allineamento

Problemi correlati