#pragma pack
instruuje kompilator, aby spakował elementy struktury ze szczególnym wyrównaniem. Większość kompilatorów, gdy deklarujesz strukturę, wstawi dopełnianie między elementami, aby upewnić się, że są one wyrównane do odpowiednich adresów w pamięci (zwykle wielokrotność wielkości typu). Pozwala to uniknąć ograniczenia wydajności (lub całkowitego błędu) w niektórych architekturach związanych z dostępem do zmiennych, które nie są odpowiednio wyrównane. Na przykład podane 4-bajtowe liczby całkowite i następująca struktura:
struct Test
{
char AA;
int BB;
char CC;
};
Kompilator może wybrać układ struktury w pamięci w następujący sposób:
| 1 | 2 | 3 | 4 |
| AA(1) | pad.................. |
| BB(1) | BB(2) | BB(3) | BB(4) |
| CC(1) | pad.................. |
i sizeof(Test)
byłoby 4 × 3 = 12, mimo że zawiera tylko 6 bajtów danych. Najczęstszym przypadkiem użycia #pragma
(według mojej wiedzy) jest praca z urządzeniami sprzętowymi, w których należy upewnić się, że kompilator nie wstawia dopełniania do danych, a każdy element jest zgodny z poprzednim. Za #pragma pack(1)
pomocą powyższej struktury będzie wyglądać następująco:
| 1 |
| AA(1) |
| BB(1) |
| BB(2) |
| BB(3) |
| BB(4) |
| CC(1) |
I sizeof(Test)
byłoby 1 × 6 = 6.
Za #pragma pack(2)
pomocą powyższej struktury będzie wyglądać następująco:
| 1 | 2 |
| AA(1) | pad.. |
| BB(1) | BB(2) |
| BB(3) | BB(4) |
| CC(1) | pad.. |
I sizeof(Test)
byłoby 2 × 4 = 8.
Ważna jest również kolejność zmiennych w struct. Ze zmiennymi uporządkowanymi w następujący sposób:
struct Test
{
char AA;
char CC;
int BB;
};
i z #pragma pack(2)
, struktura będzie wyglądać następująco:
| 1 | 2 |
| AA(1) | CC(1) |
| BB(1) | BB(2) |
| BB(3) | BB(4) |
i sizeOf(Test)
byłoby 3 × 2 = 6.
#pragma
dyrektywy, są one zdefiniowane implementacyjnie.