Dla udzielonych odpowiedzi wydaje się, że istnieje pewne niejasności co do tego, czym jest wyrównywanie. Zamieszanie powstaje prawdopodobnie dlatego, że istnieją dwa rodzaje wyrównania.
1. Wyrównanie Użytkownik
Jest to jakościowy środek, który precyzuje, jak duże instancja jest w bajtach dla konkretnego zamawiającego członków ciągu typu struktura/klasa. Ogólnie rzecz biorąc, kompilatory mogą kompaktować instancje struktury/klasy, jeśli elementy są uporządkowane według ich wielkości bajtów w porządku malejącym (tj. Najwięksi pierwsi, najmniejsi członkowie ostatni) w strukturze. Rozważ:
struct A
{
char c; float f; short s;
};
struct B
{
float f; short s; char c;
};
Obie struktury zawierają dokładnie te same informacje. Ze względu na ten przykład; typ float zajmuje 4 bajty, krótki typ zajmuje 2, a postać zajmuje 1 bajt. Jednak pierwsza struktura A ma członków w kolejności losowej, podczas gdy druga struktura B porządkuje członków zgodnie z ich rozmiarem bajtów (może to być inne na niektórych architekturach, zakładam architekturę x86 intel CPU z 4-bajtowym wyrównaniem w tym przykładzie). Teraz pod uwagę wielkość struktur:
printf("size of A: %d", sizeof (A)); // size of A: 12;
printf("size of B: %d", sizeof (B)); // size of B: 8;
Jeśli można oczekiwać rozmiar będzie 7 bajtów, można byłoby przy założeniu, że członkowie są pakowane do konstrukcji za pomocą wyrównanie 1-bajtowy. Podczas gdy niektóre kompilatory na to zezwalają, na ogół większość kompilatorów używa 4-bajtowych lub nawet 8-bajtowych dopasowań z powodów historycznych (większość pracy procesora przy użyciu rejestrów ogólnego przeznaczenia DWORD (double-word) lub QWORD (quad-word)).
Istnieją 2 mechanizmy wyściółki w pracy, aby osiągnąć opakowanie.
pierwsze, każdy element, który ma rozmiar mniejszy niż bajt bajt jest wyrównanie „połączonej” do następnego elementu (ów), jeśli uzyskany rozmiar bajtów jest mniejsza lub równa bajty wyrównania. W strukturze B elementy s i c można łączyć w ten sposób; ich łączny rozmiar wynosi 2 bajty dla s + 1 bajta dla c == 3 bajty < = wyrównanie 4 bajtowe. W przypadku struktury A nie ma takiego scalania, a każdy element efektywnie zużywa 4 bajty w strukturze opakowania.
Łączna wielkość struktury jest ponownie dopełniana, aby następna struktura mogła rozpocząć się na granicy wyrównania. W przykładzie B całkowita liczba bajtów wynosiłaby 7. Następna 4-bajtowa granica leży na bajcie 8, dlatego struktura jest wypełniona 1 bajtem, aby umożliwić przydział tablicy jako napięty ciąg instancji.
Należy zauważyć, że Visual C++/GCC umożliwiają różne wyrównania 1 bajtu, 2 i wyższych wielokrotności 2 bajtów.Zrozum, że działa to wbrew możliwości kompilatora do tworzenia optymalnego kodu dla architektury. Rzeczywiście, w poniższym przykładzie każdy bajt byłby czytany jako pojedynczy bajt przy użyciu instrukcji jednobajtowej dla każdej operacji odczytu. W praktyce sprzęt będzie nadal pobierał całą linię pamięci zawierającą każdy bajt odczytany w pamięci podręcznej i wykonuje instrukcję 4 razy, nawet jeśli 4 bajty znajdują się w tym samym DWORD i mogą być załadowane do rejestru CPU w 1 instrukcji.
#pragma pack(push,1)
struct Bad
{
char a,b,c,d;
};
#pragma pack(pop)
2. wyrównanie Przydział
ten jest ściśle związany z mechanizmem 2 do napawania opisane w poprzedniej sekcji, jednak środki przydzielone trasowania może być określona w wariantach malloc/memalloc funkcje alokacji. W związku z tym możliwe jest przydzielenie obiektu przy innej (zazwyczaj większej niż wielokrotność) granicy wyrównania niż sugeruje to wyrównanie bajtów typu struktura/obiekt.
size_t blockAlignment = 4*1024; // 4K page block alignment
void* block = malloc(sizeof(T) * count, blockAlignment);
Kod umieści blok przypadkach morfologii typu T adresów, które kończą się na wielokrotności 4096.
Powodem stosowania takich dopasowań alokacji ponownie wyłącznie architektonicznych. Na przykład czytanie i pisanie bloków z adresów wyrównanych do strony jest szybsze, ponieważ zakres adresów pasuje do warstw pamięci podręcznej. Zakresy podzielone na różne "strony" powodują usunięcie zawartości pamięci podręcznej podczas przekraczania granicy strony. Różne nośniki (architektury magistrali) mają różne wzorce dostępu i mogą korzystać z różnych dopasowań. Zasadniczo wyrównania wielkości stron o rozmiarach 4, 16, 32 i 64 K nie są rzadkie.
Spróbuj ponownie za pomocą struktur, zamiast rodzimych typów. –
'Zwraca wyrównanie w bajtach (liczba całkowita dwóch) wymagana dla każdej instancji danego typu" - http://pl.cppreference.com/w/cpp/language/alignof. 'sizeof' po prostu podaje rozmiar, oczywiście w bajtach. – chris
Być może warto wspomnieć - [sizeof jest zawsze wielokrotnością alignof] (http://stackoverflow.com/questions/4637774/is-s-size-of-a-ctct-required-to-be-an-exact-multiple -of-the-wyrównanie-of-tha) – Steve314