Nie mogłem znaleźć przyzwoitego dokumentu wyjaśniającego, jak działa system wyrównania i dlaczego niektóre typy są bardziej wyrównane niż inne.Co to jest wyrównanie danych? Dlaczego i kiedy powinienem się martwić, gdy wskaźniki literowania w C?
Odpowiedz
Spróbuję wyjaśnić w skrócie.
Co to jest wyrównanie danych?
Architektura komputera składa się z procesora i pamięci. Pamięć jest organizowana w komórkach, więc:
0x00 | data |
0x01 | ... |
0x02 | ... |
Każda komórka pamięci ma określony rozmiar, ilość bitów może przechowywać. Jest to zależne od architektury.
Po zdefiniowaniu zmiennej w swoim programie C/C++, jeden program zajmuje jedną komórkę: lub więcej.
Na przykład
int variable = 12;
Załóżmy, każda komórka zawiera 32 bitów i wielkość int
typu wynosi 32 bitów, to w gdzieś w pamięci:
variable: | 0 0 0 c | // c is hexadecimal of 12.
Kiedy Twój procesor ma pracować na tym zmienna, musi ją wprowadzić do rejestru. Procesor może pobrać "1 zegar" małą ilość bitów z pamięci, rozmiar ten jest zwykle nazywany WORD. Ten wymiar zależy również od architektury.
Teraz załóżmy, że masz zmienną, która jest przechowywana, z powodu jakiegoś przesunięcia, w dwóch komórkach.
Na przykład mam dwie różne części do przechowywania danych (mam zamiar użyć „reprezentację ciąg do bardziej jasne”):
data1: "ab"
data2: "cdef"
Więc pamięć zostanie skomponowany w taki sposób (2): różne komórki
|a b c d| |e f 0 0|
Oznacza to, data1
zajmuje tylko połowę komórki, tak data2
zajmuje pozostałą część i część drugą komórkę.
Załóżmy teraz, że procesor chce odczytać data2
. Procesor potrzebuje 2 zegarów w celu uzyskania dostępu do danych, ponieważ w ciągu jednego zegara odczytuje pierwszą komórkę, a w drugim zegarze odczytuje pozostałą część w drugiej komórce.
Jeśli możemy wyrównaćdata2
zgodnie z niniejszym pamięci-przykład, możemy wprowadzenie pewnego rodzaju wyściółką i przesunięcie data2
wszystkim w drugiej komórce.
|a b 0 0| |c d e f|
---
padding
W ten sposób procesor będzie tylko stracić „1 zegar” w celu dostępu do data2
.
Co robi system align
System align właśnie wprowadza że wyściółka aby wyrównać dane z pamięci systemu, należy pamiętać, zgodnie z architekturą. Gdy dane są wyrównane w pamięci, nie marnujesz cykli procesora w celu uzyskania dostępu do danych.
Wykonuje się to ze względów związanych z wydajnością (99% razy).
'Robi się to ze względów związanych z wydajnością (99% razy). 'IMO natychmiast powinno nastąpić zrzeczenie się, że 99% statystyk jest wytwarzanych na miejscu, a następnie dokładne wyjaśnienie możliwych przyczyn, które powodują inne' 1 % ". Podobnie jak niewyrównane dostępy powodujące pułapki, wyjątki sprzętowe itp. Mówienie o tym głównie o prędkości bez wyjaśnienia innych, często ważniejszych powodów, jest prawie wcale lepsze niż stwierdzenie, że chodzi wyłącznie o szybkość, która byłaby fałszywa. –
Jest to "definicja implementacji", tj. Wymagania dotyczące wyrównania nie są częścią specyfikacji języka.
Różne procesory mają różne wymagania dotyczące wyrównania. Niektórzy nie mogli adresować wartości 16-bitowej na nieparzystym adresie, niektórzy mogli. Niektóre z nich nie mogły zaadresować wartości zmiennoprzecinkowej, chyba że zostały wyrównane do adresu podzielnego przez jego rozmiar, inne mogłyby. I tak dalej. Niektórzy mieliby dostęp do źle wyrównanych obiektów danych wolniej niż prawidłowo wyrównane, inni mogliby przejść przez niewyrównany dostęp.
Dlatego standard językowy nie zawiera informacji o tym, który typ musi być wyrównany w określony sposób (ponieważ nie mógł), ale pozostawił go w "implementacji" - w tym przypadku w backendie kompilatora .
Jeśli wskażesz typ krojów pisma, możesz zmusić kod do adresowania danego obiektu pod adresem, do którego nie można go adresować. Należy upewnić się, że wymagania dotyczące wyrównania typu "starego" są następujące: co najmniej tak ścisłe, jak w przypadku "nowego" typu.
W języku C++ (C++ 11 w górę), operator alignof informuje o wymaganiach dotyczących wyrównania dla danego typu. Otrzymasz również operator alignas, aby wymusić bardziej ścisłe wyrównanie na danym typie lub obiekcie.
W C (C11 w górę), masz _Alignof i _Alignas operatorów, w <stdalign.h>
Chusta do alignof
/alignas
convenience macros. (Dzięki, Lundin - C11 nie jest moją mocną stroną.)
Zgodnie z C11, istnieje "_Alignof" w C. – Lundin
To jest lepsza odpowiedź na wspomnienie, że reguły dopasowania zależą od architektury istnieją dla prędkości lub konieczności - wspominając obie - podczas gdy każda inna odpowiedź skupia się tylko na jednym z dwóch do tego stopnia, że bagatelizują znaczenie drugiego czynnika niemal do zera. –
Niektóre systemy mogą uzyskać dostęp do pamięci w częściach, powiedzmy, słów 32-bitowych (4 bajty). To ograniczenie sprzętowe. Oznacza to, że rzeczywisty adres wchodzący do kontrolera pamięci powinien być podzielny przez cztery (ponieważ nadal adresuje bajty). Więc kiedy spróbujesz znaleźć słowo pod adresem, który nie jest podzielny przez cztery, istnieją dwie opcje - albo kompilator spróbuje wygenerować jakiś wymyślny kod, żeby skomponować słowo z dwóch dostępów do pamięci, ale nie zawsze tak jest. . Czasami po prostu wygeneruje kod dostępu do 4 bajtów z podanego adresu. A następnie procesor zakończy się niepowodzeniem z błędem wyrównania danych.
Co prowadzi do ograniczenia języka narzucającego się.
Rozważmy kod (zły):
uint8_t a[] = {1,2,3,4,5,6};
uint32_t b = *(uint32_t*)&a[1];
i zakładamy a
jest dostosowana do podzielna przez cztery granice. Następnie druga linia próbuje odczytać słowo z adresu jego elementu sekund, tj. Adres nie podzielny przez cztery. Doprowadzi to do błędu wyrównania. Ale w C
jest to po prostu zabronione przez ścisłą regułę aliasingu .
Kompilator gcc ma opcję '-Wcast-align', aby konkretnie ostrzegać przed takimi błędami. – hlovdal
'albo kompilator spróbuje wygenerować jakiś fantazyjny kod, aby skomponować słowo z dwóch dostępów do pamięci, ale zwykle tak nie jest." Proszę zdefiniować "zwykle". x86 może obsłużyć nieprzydzielone dostępy tylko dla podstawowych instrukcji ładowania/przechowywania przez agregowanie odczytów/zapisów, [np. link] (http://stackoverflow.com/questions/12491578/whats-the-actual-effect-efuc-uccessigned-unaligned-accesses-on-x86). I czy x86 nie jest naszym standardowym punktem odniesienia dla takich terminów jak "zwykły"? O jakich architekturach mówisz? –
@underscore_d Zamienię "zwykle" na "nie zawsze tak jest". Jestem przyzwyczajony do ARM i procesorów MCU niższej klasy, więc są dla mnie zwyczajne. –
- 1. Wycieki pamięci Angular.js, kiedy powinienem zacząć się martwić
- 2. Co to jest bajt datatype i kiedy powinienem go użyć?
- 3. Co to jest indeks pełnotekstowy i kiedy powinienem go używać?
- 4. Czy powinienem martwić się kodowaniem podczas serializacji?
- 5. Co to jest NHibernate i dlaczego powinienem go używać?
- 6. Co to są mocne wskaźniki i słabe wskaźniki
- 7. co to jest Request.InputStream i kiedy go użyć?
- 8. Co to jest sekwencja (baza danych)? Kiedy będziemy go potrzebować?
- 9. Czy powinienem się martwić o inicjatory Wmissing-field i inicjowanie agregacji w C++ 17?
- 10. const i wskaźniki w C
- 11. Przypadki testowe "kiedy", "co" i "dlaczego"?
- 12. Co to jest Manifest w Scali i kiedy go potrzebujesz?
- 13. Czy powinienem martwić się zastrzykiem PHP, jeśli nie używam MySQL?
- 14. C++ alternatywy do void * wskaźniki (nie jest to szablony)
- 15. Co to jest CGSUpdateManager i dlaczego narzeka?
- 16. Wskaźniki i alokacji pamięci w C
- 17. Co to jest metoda Javascript CollectGarbage()? Kiedy i dlaczego powinno się go używać?
- 18. Co to jest "==" w C?
- 19. Dlaczego wskaźniki zakresu w zwiększeniu
- 20. Co to jest WebIDL i (dlaczego) jest to ważne?
- 21. C# kontrolować wyrównanie danych
- 22. Co to jest protokół TDS w wersji 8.0 i dlaczego powinienem go używać?
- 23. Wskaźniki i pętle w C
- 24. C# - Co to jest komponent i jak jest zwykle używany?
- 25. c wskaźniki i tablica
- 26. Kiedy i dlaczego powinienem wdrożyć IComponent, IContainer i ISite?
- 27. Co to jest C# 5 i skąd się bierze?
- 28. Co to jest funkcja "zewnętrzna inline" i kiedy używać?
- 29. Co to są podzielniki i kiedy ich użycie jest konieczne?
- 30. C++ wyrównanie - surowe i słaby
Pamiętaj, że C i C++, chociaż są syntaktycznie podobne w niektórych częściach, są naprawdę dwoma różnymi językami z różnymi semantykami i regułami. Więc nie spamuj tagów niezwiązanych z językiem, o który naprawdę pytasz. –
Cóż, standard powinien być dość pouczający. – Downvoter
dla C++, [tutaj] (http://eel.is/c++draft/basic.align) jest tym, co standard o nim mówi – Carousel