2012-04-26 10 views
6

sto ottenendo un comportamento insolito con il mio codice, che è la seguentecomportamento dell'operatore sizeof in C

#include<stdio.h> 
struct a 
{ 
    int x; 
    char y; 
}; 
int main() 
{ 
    struct a str; 
    str.x=2; 
    str.y='s'; 
    printf("%d %d %d",sizeof(int),sizeof(char),sizeof(str)); 
    getch(); 
    return 0; 
} 

Per questo pezzo di codice che sto ottenendo l'output:

4 1 8 

Come del mio conoscenza la struttura contiene una variabile intera di dimensione 4 e una variabile char di dimensione 1, quindi la dimensione della struttura a dovrebbe essere 5. Ma come mai la dimensione della struttura è 8. Sto usando il compilatore di Visual C++. Perché questo comportamento?

+2

Negli argomenti 'printf()' dovresti lanciare i valori 'sizeof' in' (int) '... o' (unsigned long) 'e usare' "% lu" '... o, se tu avere C99, usare '"% zu "'. – pmg

+2

@ pmg: esattamente. Perché 'sizeof()' restituisce un valore di tipo 'size_t'. –

risposta

12

Si chiama Structure Padding

vista strutture di dati che si aprono su allineamento 4 word byte (sulla CPU con 4 autobus byte e processori) è molto più efficiente quando si muove intorno dati della memoria, e tra la RAM e la CPU.

In genere è possibile disattivarlo con le opzioni del compilatore e/o la direttiva, le specifiche per farlo dipenderanno dal compilatore specifico.

Spero che questo aiuti.

+1

_ In genere è possibile disattivarlo, ma non consiglio mai di farlo, anche se è necessario analizzare un pacchetto binario e avere un'idea per creare una struttura simile per la codifica/decodifica facile. Ricorda che su alcuni target (forse solo in passato) la lettura non allineata potrebbe portare al crash del processore! Inoltre questo rende il tuo codice completamente non vendibile. – Yury

+0

@Yury: se il compilatore consente '#pragma pack' o cose simili su tali piattaforme, normalmente genererà il codice per risolvere il problema di lettura allineato (tipicamente' memcpy' in una posizione separata, allineata), altrimenti tali strutture sarebbero inutilizzabili . –

8

Il compilatore inserisce il riempimento per scopi di ottimizzazione e di allineamento. Qui, il compilatore inserisce 3 byte fittizi tra (o dopo) i tuoi due membri.

È possibile gestire l'allineamento con la direttiva #pragma.

+1

forse (1) 3 byte e (2) dopo – Vlad

+0

Sì, sono 3 byte in questo caso, ma penso che sia tra, no? – md5

+0

bene, dipende dal endianness della macchina target :) iiiidddc o iiiicddd. – Vlad

0

Principalmente per illustrare il funzionamento di questo riempimento, ho modificato leggermente il programma.

#include<stdio.h> 
struct a 
{ 
    int x; 
    char y; 
    int z; 
}; 
int main() 
{ 
    struct a str; 
    str.x=2; 
    str.y='s'; 
    str.z = 13; 

    printf ("sizeof(int) = %lu\n", sizeof(int)); 
    printf ("sizeof(char) = %lu\n", sizeof(char)); 
    printf ("sizeof(str) = %lu\n", sizeof(str)); 

    printf ("address of str.x = %p\n", &str.x); 
    printf ("address of str.y = %p\n", &str.y); 
    printf ("address of str.z = %p\n", &str.z); 

    return 0; 
} 

Nota che ho aggiunto un terzo elemento alla struttura. Quando eseguo questo programma, ottengo:

[email protected]:~/so$ ./padding 
sizeof(int) = 4 
sizeof(char) = 1 
sizeof(str) = 12 
address of str.x = 0x7fffc962e070 
address of str.y = 0x7fffc962e074 
address of str.z = 0x7fffc962e078 
[email protected]:~/so$ 

La parte di questo che illustra il riempimento è evidenziata di seguito.

address of str.y = 0x7fffc962e074 
address of str.z = 0x7fffc962e078 

Mentre y è solo un carattere, notare che z è un intero 4 byte lungo.