Usa struct Alignment and Padding in C
- Comprendere le basi dell’allineamento e del riempimento in C
- Utilizzare la tecnica di riordino dei membri per risparmiare spazio negli oggetti in C
Questo articolo spiegherà diversi metodi su come usare l’allineamento e il riempimento di struct in C.
Comprendere le basi dell’allineamento e del riempimento in C
Tutti gli oggetti in memoria sono rappresentati come i tipi di dati primari come: char, short, int, long, pointer ecc. Questi tipi di dati hanno la dimensione corrispondente in memoria. Sulla maggior parte dei moderni processori desktop a 64 bit, le dimensioni sono 1 byte per un char, 2 byte per un short, 4 byte per un int, 8 byte per un pointer e così via. Nota che queste non sono dimensioni garantite (eccetto per char), ma si può recuperare la dimensione dell’oggetto usando l’operatore sizeof. Ora, l’allineamento è il metodo utilizzato dai compilatori per posizionare le variabili nella memoria, il che implica che ogni tipo di dati di base è memorizzato all’indirizzo divisibile per la dimensione corrispondente.
Di solito, l’allineamento viene utilizzato per accedere agli oggetti dati in modo più rapido ed efficiente. L’allineamento forza i diversi tipi di dati dichiarati continuamente a includere una certa spaziatura tra i loro indirizzi. Vale a dire, se dichiariamo una struttura st1 con un puntatore e un char come mostrato nell’esempio seguente, occuperà 16 byte in totale. Attenzione però, un singolo puntatore richiede 8 byte e un char richiede un byte, quindi si potrebbe pensare che la struttura st1 debba occupare 9 byte. Ma si comporta come se tutti i membri fossero allineati alla dimensione del membro più grande (cioè 8 byte). La struttura st2 mostra una struttura simile che occupa la stessa quantità di memoria, tranne per il fatto che ha un array di 7 membri char.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[]) {
typedef struct {
char *p;
char c2;
} st1;
typedef struct {
char *p;
char c2;
char padding[7];
} st2;
printf("sizeof st1 = %zu\n", sizeof(st1));
printf("sizeof st2 = %zu\n", sizeof(st2));
exit(EXIT_SUCCESS);
}
Produzione:
sizeof st1 = 16
sizeof st2 = 16
Utilizzare la tecnica di riordino dei membri per risparmiare spazio negli oggetti in C
L’esempio precedente dimostra che c’è un po’ di spreco di memoria quando le strutture includono tipi diversi e non riempiono i confini di allineamento. Tuttavia, in alcuni casi potrebbe essere possibile riordinare i membri della struttura e risparmiare spazio aggiuntivo.
Il codice di esempio successivo definisce la struttura foo1 che ha il membro più grande (char *) nel mezzo e foo2 con lo stesso membro del primo. Le dimensioni di questi due oggetti sono diverse: 24 byte e 16 byte. Ciò ha a che fare con l’ordinamento dei membri di dati. Nella struttura foo1, p deve essere allineato all’indirizzo che è divisibile per 8, quindi int e short prima occuperanno 8 byte in totale e due char * dopo occuperanno anche gli 8 byte. Sebbene, se spostiamo la p al primo posto, i seguenti membri si comprimeranno negli 8 byte e anche la regola di allineamento sarà soddisfatta. Quindi, la dimensione di foo2 ammonta a 16 byte e viene chiamato per essere compresso struct. Notare che il compilatore gcc ha lo speciale specificatore __attribute__ ((packed)) che può forzare la compressione anche dei membri struct non ordinati.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[]) {
typedef struct {
int n1;
short s1;
char *p;
char c1;
char c2;
} foo1;
typedef struct {
char *p;
int n1;
short s1;
char c1;
char c2;
} foo2;
typedef struct {
int n1;
short s1;
char *p;
char c1;
char c2;
} __attribute__((packed)) foo3;
printf("sizeof foo1 = %zu\n", sizeof(foo1));
printf("sizeof foo2 = %zu\n", sizeof(foo2));
printf("sizeof foo3 = %zu\n", sizeof(foo3));
exit(EXIT_SUCCESS);
}
Produzione:
sizeof foo1 = 24
sizeof foo2 = 16
sizeof foo3 = 16
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook