Ich arbeite gerade mit Shared Memory.
Ich kann nicht verstehen alignof
und alignas
.
cppreference ist unklar: Gibtalignof
"Ausrichtung" zurück, aber was ist "Ausrichtung"? Anzahl der hinzuzufügenden Bytes für den nächsten auszurichtenden Block? gepolsterte Größe? Stapelüberlauf / Blogeinträge sind ebenfalls unklar.
Kann jemand klar alignof
und deutlich erklären alignas
?
c++
c++11
x86-64
memory-alignment
Offirmo
quelle
quelle
alignof
Seite nicht erklärt (jetzt auf der in Bearbeitung befindlichen Objektseite ). Ich sehe nicht, wie wichtig cplusplus.com ist.Antworten:
Die Ausrichtung ist eine Einschränkung, an welchen Speicherpositionen das erste Byte eines Werts gespeichert werden kann. (Es ist erforderlich, um die Leistung auf Prozessoren zu verbessern und die Verwendung bestimmter Anweisungen zu ermöglichen, die nur für Daten mit bestimmter Ausrichtung funktionieren. Beispielsweise muss SSE auf 16 Byte und AVX auf 32 Byte ausgerichtet sein.)
Die Ausrichtung von 16 bedeutet, dass Speicheradressen, die ein Vielfaches von 16 sind, die einzigen gültigen Adressen sind.
alignas
Erzwinge die Ausrichtung auf die erforderliche Anzahl von Bytes. Sie können nur Potenzen von 2: 1, 2, 4, 8, 16, 32, 64, 128, ... ausrichten.
#include <cstdlib> #include <iostream> int main() { alignas(16) int a[4]; alignas(1024) int b[4]; printf("%p\n", a); printf("%p", b); }
Beispielausgabe:
0xbfa493e0 0xbfa49000 // note how many more "zeros" now. // binary equivalent 1011 1111 1010 0100 1001 0011 1110 0000 1011 1111 1010 0100 1001 0000 0000 0000 // every zero is just a extra power of 2
das andere Schlüsselwort
alignof
ist sehr praktisch, so etwas kann man nicht machen
int a[4]; assert(a % 16 == 0); // check if alignment is to 16 bytes: WRONG compiler error
aber du kannst es tun
assert(alignof(a) == 16); assert(alignof(b) == 1024);
Beachten Sie, dass dies in Wirklichkeit strenger ist als eine einfache "%" -Operation (Modul). Tatsächlich wissen wir, dass etwas, das auf 1024 Bytes ausgerichtet ist, notwendigerweise auf 1, 2, 4, 8 Bytes ausgerichtet ist, aber
assert(alignof(b) == 32); // fail.
Genauer gesagt gibt "alignof" die größte Potenz von 2 zurück, um etwas auszurichten.
Alignof ist auch eine gute Möglichkeit, die Mindestausrichtungsanforderungen für grundlegende Datentypen im Voraus zu kennen (wahrscheinlich wird 1 für Zeichen, 4 für Float usw. zurückgegeben).
Immer noch legal:
alignas(alignof(float)) float SqDistance;
Etwas mit einer Ausrichtung von 16 wird dann auf die nächste verfügbare Adresse gesetzt, die ein Vielfaches von 16 ist (es kann eine implizite Auffüllung von der zuletzt verwendeten Adresse geben).
quelle
sizeof
,alignof
kann nur auf ein angewendet werdentype-id
.alignof()
(und das Gegenstückalignas()
) zur Kompilierungszeit ausgewertet, also kein Laufzeitaufwand?alignof
ist eine Kompilierungszeitkonstante.alignas
ist nicht und muss durch Ihre Implementierung vonnew
(Anforderung des Standards) oder durch einen benutzerdefinierten Standard- Allokator unterstützt werden .struct
und Mitgliedern der Struktur, die sindstatic
.alignas
stellt sich als viel kniffliger heraus__attribute__((aligned))
, besonders unter Compilern wie Clang.Die Ausrichtung ist keine Polsterung (obwohl manchmal eine Polsterung eingeführt wird, um die Ausrichtungsanforderungen zu erfüllen). Es ist eine intrisische Eigenschaft eines C ++ - Typs. Um es in Standardese (
3.11[basic.align]
) zu setzenquelle
struct X { char a; char b}
hat Größe 2 und Ausrichtungsanforderung 1 auf vernünftigen Systemen (es kann an jeder Adresse zugewiesen werden, da ein Zeichen an jeder Adresse zugewiesen werden kann)alignof(std::max_align_t)
, was16
unter meinem Linux ist (unabhängig davon, ob -m32 oder -m64 kompiliert), aber Sie können es strenger machen mitalignas
Jeder Typ hat eine Ausrichtungsanforderung. Im Allgemeinen ist dies so, dass auf Variablen des Typs effizient zugegriffen werden kann, ohne dass die CPU mehr als einen Lese- / Schreibzugriff generieren muss, um ein bestimmtes Mitglied des Datentyps zu erreichen. Darüber hinaus wird ein effizientes Kopieren der gesamten Variablen sichergestellt.
alignof
gibt die Ausrichtungsanforderung für den angegebenen Typ zurück.alignas
wird verwendet, um eine Ausrichtung eines Datentyps zu erzwingen (sofern nicht weniger streng ist,alignof
dass der Datentyp zurückgegeben wird)quelle
Die Ausrichtung ist eine Eigenschaft, die sich auf die Speicheradresse bezieht. Wir können einfach sagen, dass wenn eine Adresse X auf Z ausgerichtet ist, x ein Vielfaches von Z ist, dh X = Zn + 0. Hier ist es wichtig, dass Z immer eine Potenz von 2 ist.
Die obige Anweisung befindet sich in der Microsoft C ++ - Referenz.
Wenn ein Datenelement mit einer Adresse im Speicher gespeichert ist, die auf seine Größe ausgerichtet ist, wird dieses Datenelement als natürlich ausgerichtet bezeichnet , andernfalls wird es falsch ausgerichtet. Zum Beispiel: Wenn eine ganzzahlige Variable mit einer Größe von 4 Bytes in einer Adresse gespeichert ist, die auf 4 ausgerichtet ist, können wir sagen, dass die Variable natürlich ausgerichtet ist, dh die Adresse der Variablen sollte ein Vielfaches von 4 sein.
Die Compiler versuchen immer, Fehlausrichtungen zu vermeiden. Für einfache Datentypen werden die Adressen so gewählt, dass sie ein Vielfaches der Größe der Variablen in Bytes sind. Der Complier ist auch bei Strukturen für die natürliche Ausrichtung und den natürlichen Zugriff geeignet. Hier wird die Struktur auf das Maximum der Größe verschiedener Datenelemente in der Struktur ausgerichtet.
struct abc { int a; char b; };
Hier ist die Struktur abc auf 4 ausgerichtet, was der Größe des int-Elements entspricht, die offensichtlich größer als 1 Byte ist (Größe des char-Elements).
alignas
Dieser Bezeichner wird verwendet, um benutzerdefinierte Typen wie Struktur, Klasse usw. an einem bestimmten Wert auszurichten, der eine Potenz von 2 ist.
ausrichten
Dies ist eine Art Operator, um den Wert abzurufen, an dem die Struktur oder der Klassentyp ausgerichtet ist. z.B:
#include <iostream> struct alignas(16) Bar { int i; // 4 bytes int n; // 4 bytes short s; // 2 bytes }; int main() { std::cout << alignof(Bar) << std::endl; // output: 16 }
quelle