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?

È stato utile?

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.

wikipedia articolo :

  

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.

     
      
  1. #pragma pack(n) imposta semplicemente il nuovo allineamento.
  2.   
  3. #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).
  4.   
  5. #pragma pack(push[,n]) spinge l'impostazione di allineamento corrente su un   stack interno e quindi opzionalmente   imposta il nuovo allineamento.
  6.   
  7. #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).
  8.   
     

Alcuni obiettivi, per esempio i386 e PowerPC,   sostenere la #pragma ms_struct che   delinea una struttura come documentato   __attribute__ ((ms_struct)).

     
      
  1. giri #pragma ms_struct on sul layout per le strutture dichiarato.
  2.   
  3. giri #pragma ms_struct off fuori il layout per le strutture dichiarato.
  4.   
  5. #pragma ms_struct reset risale al layout predefinito.
  6.   
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top