Ausrichtung
Eines der Features von C++ auf niedriger Ebene ist die Möglichkeit zum Angeben der präzisen Ausrichtung von Objekten im Speiche, um eine bestimmte Hardwarearchitektur optimal zu nutzen. Standardmäßig richtet der Compiler Klassen- und Strukturmber an seinen Größenwerten aus: bool
und char
auf 1-Byte-Begrenzungen, short
auf 2-Byte-Begrenzungen, int
, long
und float
auf 4-Byte-Begrenzungen und , double
und , und long long
long double
auf 8-Byte-Begrenzungen.
In den meisten Szenarien müssen Sie sich nie mit der Ausrichtung befassen, da die Standardausrichtung bereits optimal ist. In einigen Fällen können Sie jedoch erhebliche Leistungsverbesserungen oder Speichereinsparungen erzielen, indem Sie eine benutzerdefinierte Ausrichtung für Ihre Datenstrukturen angeben. Vor Visual Studio 2015 können Sie die microsoftspezifischen Schlüsselwort (keyword) __alignof
verwenden und __declspec(align)
eine Ausrichtung angeben, die größer als die Standardeinstellung ist. Ab Visual Studio 2015 sollten Sie die C++11-Standard-Schlüsselwort (keyword) und alignof
alignas
die maximale Codeübertragbarkeit verwenden. Die neuen Schlüsselwort (keyword) verhalten sich auf die gleiche Weise wie die microsoftspezifischen Erweiterungen. Die Dokumentation für diese Erweiterungen gilt auch für die neuen Schlüsselwort (keyword). Weitere Informationen finden Sie unter alignof
Operator, alignas
Bezeichner und Ausrichten. Der C++-Standard gibt kein Verpackungsverhalten für die Ausrichtung auf Begrenzungen an, die kleiner als der Compilerstandard für die Zielplattform sind. Daher müssen Sie microsoft #pragma pack
in diesem Fall weiterhin verwenden.
Verwenden Sie die aligned_storage Klasse für die Speicherzuordnung von Datenstrukturen mit benutzerdefinierten Ausrichtungen. Die aligned_union Klasse dient zum Angeben der Ausrichtung für Gewerkschaften mit nichttriviellen Konstruktoren oder Destruktoren.
Ausrichtungs- und Speicheradressen
Die Ausrichtung ist eine Eigenschaft einer Speicheradresse, ausgedrückt als numerisches Adressmodulo der Potenz 2. Beispielsweise ist die Adresse 0x0001103F Modulo 4 3. Diese Adresse soll an 4n+3 ausgerichtet werden, wobei 4 die gewählte Potenz von 2 angibt. Die Ausrichtung einer Adresse hängt von der gewählten Potenz von 2 ab. Das gleiche Adressmodulo 8 ist 7. Eine Adresse wird als an X ausgerichtet betrachtet, wenn die Ausrichtung Xn+ 0 ist.
CPUs führen Anweisungen aus, die mit daten arbeiten, die im Arbeitsspeicher gespeichert sind. Die Daten werden durch ihre Adressen im Arbeitsspeicher identifiziert. Ein einzelnes Datum hat auch eine Größe. Ein Datum wird natürlich ausgerichtet , wenn seine Adresse an seine Größe ausgerichtet ist. Andernfalls wird sie falsch ausgerichtet . Beispielsweise wird ein Gleitkomma-Datum mit 8 Byte natürlich ausgerichtet, wenn die Adresse, mit der sie identifiziert wird, eine 8-Byte-Ausrichtung aufweist.
Compilerverarbeitung der Datenausrichtung
Compiler versuchen, Datenzuordnungen auf eine Weise vorzunehmen, die eine Fehlausrichtung von Daten verhindert.
Der Compiler weist für einfache Datentypen Adressen zu, die ein Vielfaches der Größe in Bytes des Datentyps entsprechen. Beispielsweise weist der Compiler Variablen des Typs long
Adressen zu, die Vielfache von 4 sind, wobei die untersten 2 Bits der Adresse auf Null festgelegt werden.
Der Compiler sorgt auch dafür, dass strukturen so ausgerichtet werden, dass jedes Element der Struktur natürlich ausgerichtet wird. Betrachten Sie die Struktur struct x_
im folgenden Codebeispiel:
struct x_
{
char a; // 1 byte
int b; // 4 bytes
short c; // 2 bytes
char d; // 1 byte
} bar[3];
Der Compiler füllt die Struktur, um die natürliche Ausrichtung zu erzwingen.
Das folgende Codebeispiel zeigt, wie der Compiler die aufgefüllte Struktur im Arbeitsspeicher platziert:
// Shows the actual memory layout
struct x_
{
char a; // 1 byte
char _pad0[3]; // padding to put 'b' on 4-byte boundary
int b; // 4 bytes
short c; // 2 bytes
char d; // 1 byte
char _pad1[1]; // padding to make sizeof(x_) multiple of 4
} bar[3];
Beide Deklarationen werden als 12 Byte zurückgegeben sizeof(struct x_)
.
Die zweite Deklaration enthält zwei Auffüllelemente:
char _pad0[3]
um dasint b
Element an einer Grenze von 4 Byte auszurichten.char _pad1[1]
um die Arrayelemente der Strukturstruct _x bar[3];
an einer Grenze von 4 Byte auszurichten.
Der Abstand richtet die Elemente bar[3]
auf eine Weise aus, die den natürlichen Zugriff ermöglicht.
Das folgende Codebeispiel zeigt das bar[3]
Arraylayout:
adr offset element
------ -------
0x0000 char a; // bar[0]
0x0001 char pad0[3];
0x0004 int b;
0x0008 short c;
0x000a char d;
0x000b char _pad1[1];
0x000c char a; // bar[1]
0x000d char _pad0[3];
0x0010 int b;
0x0014 short c;
0x0016 char d;
0x0017 char _pad1[1];
0x0018 char a; // bar[2]
0x0019 char _pad0[3];
0x001c int b;
0x0020 short c;
0x0022 char d;
0x0023 char _pad1[1];
alignof
und alignas
Der alignas
Bezeichner ist eine tragbare, C++-Standardmethode zum Angeben der benutzerdefinierten Ausrichtung von Variablen und benutzerdefinierten Typen. Der alignof
Operator ist ebenfalls eine standardmäßige, portierbare Methode zum Abrufen der Ausrichtung eines angegebenen Typs oder einer Variablen.
Beispiel
Sie können für eine Klasse, Struktur oder Vereinigung oder für einzelne Mitglieder verwenden alignas
. Wenn mehrere alignas
Bezeichner gefunden werden, wählt der Compiler den Wert mit dem größten Wert aus.
// alignas_alignof.cpp
// compile with: cl /EHsc alignas_alignof.cpp
#include <iostream>
struct alignas(16) Bar
{
int i; // 4 bytes
int n; // 4 bytes
alignas(4) char arr[3];
short s; // 2 bytes
};
int main()
{
std::cout << alignof(Bar) << std::endl; // output: 16
}
Siehe auch
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für