Mam tło C #. Jestem bardzo nowicjuszem w języku niskiego poziomu, takim jak C.
W języku C # struct
pamięć jest domyślnie układana przez kompilator. Kompilator może niejawnie zmienić kolejność pól danych lub wstawić dodatkowe bity między polami. Musiałem więc określić specjalny atrybut, aby zastąpić to zachowanie dla dokładnego układu.
AFAIK, C nie zmienia kolejności ani nie wyrównuje układu pamięci struct
domyślnie. Słyszałem jednak, że jest mały wyjątek, który jest bardzo trudny do znalezienia.
Jakie jest zachowanie układu pamięci w C? Co powinno zostać ponownie uporządkowane / wyrównane, a czego nie?
źródło
#pragma pack
ale z bardziej szczegółową kontrolą nad semantyką._Alignas
.Jest to specyficzne dla implementacji, ale w praktyce zasada (w przypadku braku
#pragma pack
lub podobnych) to:sizeof(T)
bajtów.Tak więc, biorąc pod uwagę następującą strukturę:
struct ST { char ch1; short s; char ch2; long long ll; int i; };
ch1
jest na przesunięciu 0s
przy odsunięciu 2ch2
jest na przesunięciu 4, bezpośrednio po sll
przy odsunięciu 8i
jest na przesunięciu 16, tuż za llWięc
sizeof(ST)
jest 24.Można go zmniejszyć do 16 bajtów, zmieniając układ elementów, aby uniknąć wypełnienia:
struct ST { long long ll; // @ 0 int i; // @ 8 short s; // @ 12 char ch1; // @ 14 char ch2; // @ 15 } ST;
źródło
char
członka do swojego przykładu.sizeof(T)
bajtów. Na przykładdouble
typowa architektura 32-bitowa ma 8 bajtów, ale często wymaga tylko 4-bajtowego wyrównania . Ponadto wyściółka na końcu struktury tylko dopasowuje się do wyrównania najszerszego elementu konstrukcji. Na przykład struktura składająca się z 3 zmiennych typu char może nie mieć wypełnienia.Możesz zacząć od przeczytania artykułu poświęconego dopasowaniu struktury danych w Wikipedii, aby lepiej zrozumieć wyrównanie danych.
Z artykułu w Wikipedii :
Od 6.54.8 Pragmy pakowania struktury w dokumentacji GCC:
źródło