2015-08-14 10 views
8

Sto utilizzando __attribute__((packed)) per evitare il riempimento della struttura. Il codice seguente funziona correttamente, ma quando aggiungo un altro membro int all'interno della struct, il compilatore esegue il pad della mia struct.Evitare il riempimento della struttura in c utilizzando __attribute __ ((impacchettato))

#include <stdio.h> 

struct test { 

    int x; 
    char c1; 
    char c2; 
    char c3; 
    char c4; 
    char c5; 
    // int d; Pads if I uncomment 

} __attribute__((packed)) obj = {50,'X','Y','Z','A','B'}; 

int main() 
{ 
    struct test *ptr= &obj; 
    char *ind = (char *) &obj; 

    printf("\nLet's see what is the address of obj %d", ptr); 
    printf("\n Size of obj is : %d bytes ", sizeof(obj)); 
    printf("\nAddress of x is %d", &ptr->x); 
    printf("\nAddress of c1 is %d", &ptr->c1); 
    printf("\nAddress of c2 is %d", &ptr->c2); 
    printf("\nValue of x is %d", ptr->x); 
    printf("\nAddress of x is %c", ptr->c1); 
    printf("\nFetching value of c4 through offset %c", *(ind+7)); 

} 

Il codice precedente funziona come previsto e la dimensione di obj è 9 byte (con imbottitura era 12 byte).

Tuttavia, quando scommentare int d nel mio struct uscite codice:

Superficie obj é: 16 byte

invece dei 13 (9 + 4) byte attesi.

Cosa c'è che non va?

+0

Per quale CPU si sta compilando? –

+1

Hai provato a racchiudere la struttura tra '#pragma pack (push, 1)' e '#pragma pack (pop)' che credo sia parte di gcc (invece di usare l'attributo)? Con MSVC, si ottengono le dimensioni 9 e 13. –

+0

Per lo più osservo questa domanda per vedere come si sviluppa, ma questo potrebbe essere rilevante: http://www.bttr-software.de/forum/mix_entry.php?id=11767. Sembra che l'idea di imballaggio di GCC possa in qualche modo essere una bugia. Non ho letto l'intero thread, ma forse ci sono alcune opzioni del compilatore che lo faranno sparire, a seconda del tuo esatto compilatore (versione inclusa), CPU e sistema operativo. Sospetto anche che forse il compilatore abbia ancora il diritto di tamponare alla fine, ma non nel mezzo. Cosa succede se metti 'd' dopo 'c1'? Il padding sarebbe ancora alla fine della struct o tra c1 e d? – Dmitri

risposta

1

Nelle strutture sono coinvolti due tipi di riempimento. (1) Riempimento aggiunto per rendere la struttura un multiplo di un certo numero (Nel tuo caso la dimensione di int) e (2) Riempimento aggiunto per posizionare determinati tipi di dati in un indirizzo divisibile per un certo numero. Ad esempio, 4 byte per int. Quindi nel tuo caso, mentre il compilatore è felice di rimuovere il primo tipo di padding, penso che stia ancora costringendo il membro int d a un indirizzo divisibile per 4. Dato che ci sono 5 caratteri prima di d, viene aggiunto 3 byte di padding per forzare d a un indirizzo divisibile per 4.

Quindi prova a spostare il membro int d sopra i caratteri. Quindi, naturalmente, è necessario modificare l'offset utilizzato in fetching value of c4 through offset. Puoi persino posizionarlo sopra lo c5. Quindi non dovresti cambiare la tua linea fetching value of c4 through offset. Esempio:

struct test { 

    int x; 
    int d; 
    char c1; 
    char c2; 
    char c3; 
    char c4; 
    char c5; 

} __attribute__((packed)) obj = {50,'X','Y','Z','A','B'}; 

O

struct test { 

    int x; 
    char c1; 
    char c2; 
    char c3; 
    char c4; 
    int d; 
    char c5; 

} __attribute__((packed)) obj = {50,'X','Y','Z','A','B'}; 
0

Grazie a tutti coloro che hanno trovato il tempo per entrare in peculiarità .I vorrebbe dire al comportamento del compilatore, che sto utilizzando dopo aver fatto i controlli diversi e vorrebbe attaccare al fatto che in entrambi gli scenari vale a dire con e senza il padding il compilatore vuole che l'intero membro ricada sull'indirizzo che è divisibile per la sua dimensione, in questo caso 4 byte, (pad interposti) che sebbene non definisca l'attributo ' 'funzionando comunque servono ancora buoni propositi. Come sappiamo e presumo compilatore ri con maggiore enfasi sulla velocità anziché sullo spazio e quindi risparmiare tempo nell'effettuare le istruzioni e risparmiare il ciclo della macchina. Strictly Following protocollo precedente, se il compilatore presume che il prossimo membro che incontra sia intero, allora è la condizione migliore perché il compilatore non dovrà preoccuparsi di riempimento o assenza di padding perché il prossimo intero sarà sicuramente in grado di cadere sull'indirizzo divisibile per 4 (byte). È ancora meglio se double è una dimensione di 4 byte come in linux 32 bit arch. Una cosa che posso assicurare è che in assenza di padding (facendo uso di attributo) il compilatore evita pad alla fine ma in caso di pad pad del compilatore tra parent e in fine per rendere la dimensione della struttura divisibile per 4. (perché struct size che è divisibile per 8 (doppia dimensione su qualche macchina) è divisibile anche per 4). Come domanda e funzionamento è totalmente compilatore basato quindi non era giusto a tutti, ecco perché ancora di più grazie.

Problemi correlati