layout di memoria struct C
-
02-10-2019 - |
Domanda
Ho un background C #. Sono molto un novizio di un linguaggio di basso livello come C.
In C #, la memoria di struct
è disposto dal compilatore di default. Il compilatore può riordinare i campi dati o pad bit aggiuntivi tra i campi implicitamente. Così, ho dovuto specificare alcune attributo speciale per ignorare questo comportamento per il layout esatto.
AFAIK, C non si riordino o allineamento layout della memoria di un struct
predefinita. Tuttavia, ho sentito che c'è un po 'di eccezione che è molto difficile da trovare.
Qual è il comportamento layout di memoria di C? Quale dovrebbe essere riordinata / allineato e non?
Soluzione
In C, il compilatore è permesso di dettare qualche allineamento per ogni tipo primitivo. Tipicamente l'allineamento è la dimensione del tipo. Ma è del tutto implementazione-specifici.
byte di riempimento vengono introdotti così ogni oggetto è allineata correttamente. Riordinamento non è permesso.
Forse ogni remoto moderni strumenti di compilazione #pragma pack
che permette il controllo su imbottitura e lascia al programmatore di rispettare l'ABI. (È rigorosamente non standard, però.)
Da C99 §6.7.2.1:
12 Ogni membro non bit-field di una struttura o unione oggetto viene allineato in un modo definito specifica di esecuzione adeguato al suo tipo.
Nel giro di un 13 oggetto struttura, il non-bit-field membri e le unità in cui bit-field risiedere avere indirizzi che aumentare nell'ordine in cui essi sono dichiarati. Un puntatore a una struttura oggetto, opportunamente convertito, punti di suo membro iniziale (o se quel membro è un campo di bit, quindi all'unità in cui risiede), e viceversa. Ci possono essere imbottitura senza nome all'interno di una struttura dell'oggetto, ma non al suo inizio.
Altri suggerimenti
E 'di implementazione specifico, ma in pratica la regola (in assenza di #pragma pack
o simili) è:
-
membri
- Struct vengono memorizzati nell'ordine in cui sono dichiarati. (Questo è richiesto dalla norma C99, come accennato in precedenza qui.)
- Se necessario, si aggiunge imbottitura prima di ogni membro struct, per assicurare un allineamento corretto.
- Ogni tipo primitivo T richiede un allineamento di byte
sizeof(T)
.
Quindi, dato il seguente struct:
struct ST
{
char ch1;
short s;
char ch2;
long long ll;
int i;
};
-
ch1
è all'offset 0 - un byte di padding è inserito al align ...
-
s
all'offset 2 -
ch2
è all'offset 4, subito dopo s - 3 byte di riempimento sono inseriti per allineare ...
-
ll
all'offset 8 -
i
è all'offset 16, subito dopo ll - 4 byte di riempimento sono aggiunte alla fine in modo che la struct complessivo è un multiplo di 8 byte. Ho controllato questo su un sistema a 64 bit:. Sistemi a 32 bit possono consentire di avere struct allineamento a 4 byte
Quindi sizeof(ST)
è 24.
Può essere ridotto a 16 byte riposizionando i membri di padding evitare:
struct ST
{
long long ll; // @ 0
int i; // @ 8
short s; // @ 12
char ch1; // @ 14
char ch2; // @ 15
} ST;
È possibile iniziare leggendo le struttura dati dell'articolo allineamento wikipedia per ottenere una migliore comprensione di allineamento dei dati.
Dati mezzi di allineamento mettendo i dati in una memoria di correzione pari a un multiplo della dimensione della parola, che aumenta le prestazioni del sistema a causa del modo in cui la memoria maniglie CPU. Per allineare i dati, può essere necessario inserire alcuni byte insignificanti tra la fine dell'ultima struttura di dati e l'inizio del successivo, che è la struttura dati di riempimento.
6.54.8 Struttura-Packing Pragma del GCC documentazione:
Per la compatibilità con Microsoft compilatori di Windows, GCC supporta un insieme delle direttive #pragma che cambiano la massimo allineamento dei componenti Strutture (diversi da zero-width campi di bit), sindacati, e le classi successivamente definito. Il valore n sotto sempre è richiesto per essere un piccolo potenza di due e specifica il nuovo allineamento in byte.
#pragma pack(n)
imposta semplicemente il nuovo allineamento.#pragma pack()
imposta l'allineamento a quello che era in effetto quando la compilazione avviato (vedi anche comandare opzione della riga -fpack-struct [=] vedi codice Opzioni a Richiesta).#pragma pack(push[,n])
spinge l'impostazione di allineamento corrente su un stack interno e quindi opzionalmente imposta il nuovo allineamento.#pragma pack(pop)
ripristina l'impostazione di allineamento a quello salvato in la parte superiore della pila interna (e rimuove quella voce stack). Nota che#pragma pack([n])
non influenza questo stack interno; quindi è possibile avere#pragma pack(push)
seguita da#pragma pack(n)
multipla istanze e finalizzato da un singolo#pragma pack(pop)
.Alcuni obiettivi, per esempio i386 e PowerPC, sostenere la
#pragma
ms_struct che delinea una struttura come documentato__attribute__ ((ms_struct))
.
- giri
#pragma ms_struct on
sul layout per le strutture dichiarato.- giri
#pragma ms_struct off
fuori il layout per le strutture dichiarato.#pragma ms_struct reset
risale al layout predefinito.