Ausrichtung (C11)
Eines der Features von C auf niedriger Ebene ist die Möglichkeit zum Angeben der präzisen Ausrichtung von Objekten im Speiche, um die Hardwarearchitektur optimal zu nutzen.
Das Lesen aus dem und Schreiben in den Arbeitsspeicher durch CPUs ist effizienter, wenn Daten an einer Adresse gespeichert werden, die ein Vielfaches der Datengröße ist. Beispielsweise wird auf einen 4-Byte-Integerwert effizienter zugegriffen, wenn er an einer Adresse gespeichert ist, die ein Vielfaches von 4 ist. Wenn die Daten nicht ausgerichtet sind, ist der CPU-Aufwand für die Adressberechnung größer, um auf die Daten zuzugreifen.
Standardmäßig richtet der Compiler Daten basierend auf ihrer Größe aus: char
an einer 1-Byte-Grenze; short
an einer 2-Byte-Grenze; int
, long
und float
an einer 4-Byte-Grenze, double
an einer 8-Byte-Grenze usw.
Darüber hinaus verbessern Sie durch die Ausrichtung häufig verwendeter Daten an der Cachezeilengröße des Prozessors die Cacheleistung. Angenommen, Sie definieren eine Struktur, deren Größe kleiner als 32 Bytes ist. Sie sollten dann eine 32-Byte-Ausrichtung verwenden, um sicherzustellen, dass alle Instanzen der Struktur effizient zwischengespeichert werden.
Normalerweise müssen Sie sich keine Gedanken bezüglich der Ausrichtung machen. Der Compiler richtet Daten in der Regel an natürlichen Grenzen aus, die auf dem Zielprozessor und der Größe der Daten basieren. Daten werden an bis zu 4-Byte-Grenzen mit 32-Bit-Prozessoren und 8-Byte-Grenzen mit 64-Bit-Prozessoren ausgerichtet. In einigen Fällen erzielen Sie jedoch Leistungsverbesserungen oder Speicherplatzeinsparungen, indem Sie eine benutzerdefinierte Ausrichtung für Ihre Datenstrukturen angeben.
Verwenden Sie das C11-Schlüsselwort _Alignof
, um die bevorzugte Ausrichtung eines Typs oder einer Variablen zu erhalten, und _Alignas
, um eine benutzerdefinierte Ausrichtung für eine Variable oder einen benutzerdefinierten Typ anzugeben.
Die Convenience-Makros alignof
und alignas
, die in <stdalign.h>
definiert sind, sind direkt _Alignof
bzw. _Alignas
zugeordnet. Diese Makros entsprechen den in C++ verwendeten Schlüsselwörtern. Daher ist es möglicherweise hilfreich, die Makros aus Gründen der Codeportabilität anstelle der C-Schlüsselwörter zu verwenden, wenn Sie Code zwischen den beiden Sprachen freigeben.
alignas
und _Alignas
(C11)
Verwenden Sie alignas
oder _Alignas
, um die benutzerdefinierte Ausrichtung für eine Variable oder einen benutzerdefinierten Typ anzugeben. Sie können auf eine Struktur, eine Union, eine Enumeration oder eine Variable angewendet werden.
alignas
-Syntax
alignas(type)
alignas(constant-expression)
_Alignas(type)
_Alignas(constant-expression)
Bemerkungen
_Alignas
kann nicht in der Deklaration einer Typdefinition, eines Bitfelds, einer Funktion, eines Funktionsparameters oder eines mit dem register
-Spezifizierer deklarierten Objekts verwendet werden.
Geben Sie eine Ausrichtung an, die eine Potenz von zwei ist, z. B. 1, 2, 4, 8, 16 usw. Verwenden Sie keinen Wert, der kleiner als die Größe des Typs ist.
struct
- und union
-Typen haben eine Ausrichtung, die der größten Ausrichtung eines beliebigen Members entspricht. In struct
werden Auffüllbytes hinzugefügt, um sicherzustellen, dass die Ausrichtungsanforderungen einzelner Member erfüllt werden.
Wenn mehrere alignas
-Spezifizierer in einer Deklaration vorhanden sind (z. B. struct
mit mehreren Membern, die unterschiedliche alignas
-Spezifizierer aufweisen), entspricht die Ausrichtung von struct
mindestens dem Wert des größten Spezifizierers.
alignas
-Beispiel
In diesem Beispiel wird das Convenience-Makro alignof
verwendet, da es in C++ portierbar ist. Das Verhalten ist identisch, wenn Sie _Alignof
verwenden.
// Compile with /std:c11
#include <stdio.h>
#include <stdalign.h>
typedef struct
{
int value; // aligns on a 4-byte boundary. There will be 28 bytes of padding between value and alignas
alignas(32) char alignedMemory[32]; // assuming a 32 byte friendly cache alignment
} cacheFriendly; // this struct will be 32-byte aligned because alignedMemory is 32-byte aligned and is the largest alignment specified in the struct
int main()
{
printf("sizeof(cacheFriendly): %d\n", sizeof(cacheFriendly)); // 4 bytes for int value + 32 bytes for alignedMemory[] + padding to ensure alignment
printf("alignof(cacheFriendly): %d\n", alignof(cacheFriendly)); // 32 because alignedMemory[] is aligned on a 32-byte boundary
/* output
sizeof(cacheFriendly): 64
alignof(cacheFriendly): 32
*/
}
alignof
und _Alignof
(C11)
_Alignof
und der zugehörige Alias alignof
geben die Ausrichtung des angegebenen Typs in Bytes zurück. Es wird ein Wert vom Typ size_t
zurückgegeben.
alignof
-Syntax
alignof(type)
_Alignof(type)
alignof
-Beispiel
In diesem Beispiel wird das Convenience-Makro alignof
verwendet, da es in C++ portierbar ist. Das Verhalten ist identisch, wenn Sie _Alignof
verwenden.
// Compile with /std:c11
#include <stdalign.h>
#include <stdio.h>
int main()
{
size_t alignment = alignof(short);
printf("alignof(short) = %d\n", alignment); // 2
printf("alignof(int) = %d\n", alignof(int)); // 4
printf("alignof(long) = %d\n", alignof(long)); // 4
printf("alignof(float) = %d\n", alignof(float)); // 4
printf("alignof(double) = %d\n", alignof(double)); // 8
typedef struct
{
int a;
double b;
} test;
printf("alignof(test) = %d\n", alignof(test)); // 8 because that is the alignment of the largest element in the structure
/* output
alignof(short) = 2
alignof(int) = 4
alignof(long) = 4
alignof(float) = 4
alignof(double) = 8
alignof(test) = 8
*/
}
Anforderungen
Kompilieren Sie mit /std:c11
.
Windows SDK 10.0.20348.0 (Version 2104) oder höher. Informationen zum Herunterladen des neuesten SDK finden Sie unter Windows SDK. Anweisungen zum Installieren und Verwenden des SDK für die C11- und C17-Entwicklung finden Sie unter Installieren der Unterstützung für C11 und C17 in Visual Studio.
Siehe auch
/std
(Standardversion für die Sprache festlegen)
C++alignof
und alignas
Compilerverarbeitung der Datenausrichtung