Wyrównanie (C11)
Jedną z funkcji niskiego poziomu języka C jest możliwość określenia dokładnego wyrównania obiektów w pamięci w celu maksymalnego wykorzystania architektury sprzętowej.
Procesory CPU odczytują i zapisują pamięć wydajniej podczas przechowywania danych pod adresem, który jest wielokrotnym rozmiarem danych. Na przykład 4-bajtowa liczba całkowita jest uzyskiwana wydajniej, jeśli jest przechowywana pod adresem wielokrotnym 4. Gdy dane nie są wyrównane, procesor wykonuje więcej obliczeń adresowych w celu uzyskania dostępu do danych.
Domyślnie kompilator wyrównuje dane na podstawie jego rozmiaru: char
na granicy 1-bajtowej, short
na granicy 2-bajtowej, int
, long
i float
na granicy 4-bajtowej, double
na granicy 8 bajtów itd.
Ponadto dzięki wyrównaniu często używanych danych z rozmiarem wiersza pamięci podręcznej procesora można zwiększyć wydajność pamięci podręcznej. Załóżmy na przykład, że definiujesz strukturę, której rozmiar jest mniejszy niż 32 bajty. Możesz użyć wyrównania 32 bajtów, aby zapewnić wydajne buforowanie wszystkich wystąpień struktury.
Zwykle nie musisz martwić się o wyrównanie. Kompilator zwykle wyrównuje dane na granicach naturalnych, które są oparte na procesorze docelowym i rozmiarze danych. Dane są wyrównane do 4-bajtowych granic procesorów 32-bitowych i granic 8 bajtów na procesorach 64-bitowych. W niektórych przypadkach można jednak osiągnąć poprawę wydajności lub oszczędność pamięci, określając niestandardowe wyrównanie struktur danych.
Użyj słowa kluczowego _Alignof
C11, aby uzyskać preferowane wyrównanie typu lub zmiennej i _Alignas
określić niestandardowe wyrównanie dla zmiennej lub typu zdefiniowanego przez użytkownika.
Makra wygody alignof
i alignas
, zdefiniowane w <stdalign.h>
pliku , mapuj bezpośrednio na _Alignof
i _Alignas
, odpowiednio. Te makra pasują do słów kluczowych używanych w języku C++. Dlatego użycie makr zamiast słów kluczowych języka C może być przydatne w przypadku przenoszenia kodu, jeśli udostępniasz dowolny kod między dwoma językami.
alignas
i _Alignas
(C11)
Użyj alignas
polecenia lub _Alignas
, aby określić niestandardowe wyrównanie dla zmiennej lub typu zdefiniowanego przez użytkownika. Można je zastosować do struktury, unii, wyliczenia lub zmiennej.
Składnia aparatu alignas
alignas(type)
alignas(constant-expression)
_Alignas(type)
_Alignas(constant-expression)
Uwagi
_Alignas
Nie można użyć w deklaracji typedef, bit-field, funkcji, parametru funkcji lub obiektu zadeklarowanego za pomocą specyfikatora register
.
Określ wyrównanie, które jest potęgą dwóch, na przykład 1, 2, 4, 8, 16 itd. Nie używaj wartości mniejszej niż rozmiar typu.
struct
typy i union
mają wyrównanie równe największemu wyrównaniu każdego elementu członkowskiego. Dopełnianie bajtów jest dodawane w ramach elementu w struct
celu zapewnienia spełnienia wymagań dotyczących wyrównania poszczególnych elementów członkowskich.
Jeśli istnieje kilka alignas
specyfikatorów w deklaracji (na przykład z kilkoma elementami członkowskimi, struct
które mają różne alignas
specyfikatory), wyrównanie struct
specyfikatora będzie co najmniej wartością największego specyfikatora.
alignas
przykład
W tym przykładzie użyto makra alignof
wygody, ponieważ jest to przenośne z językiem C++. Zachowanie jest takie samo, jeśli używasz polecenia _Alignof
.
// 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
i _Alignof
(C11)
_Alignof
a jego alias alignof
zwraca wyrównanie w bajtach określonego typu. Zwraca wartość typu size_t
.
Składnia aparatu alignof
alignof(type)
_Alignof(type)
alignof
przykład
W tym przykładzie użyto makra alignof
wygody, ponieważ jest to przenośne z językiem C++. Zachowanie jest takie samo, jeśli używasz polecenia _Alignof
.
// 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
*/
}
Wymagania
Skompiluj za pomocą polecenia /std:c11
.
Windows SDK 10.0.20348.0 (wersja 2104) lub nowsza. Zobacz Zestaw Windows SDK , aby pobrać najnowszy zestaw SDK. Aby uzyskać instrukcje dotyczące instalowania i używania zestawu SDK dla programowania C11 i C17, zobacz Instalowanie obsługi C11 i C17 w programie Visual Studio.
Zobacz też
/std
(Określ wersję standardową języka)
C++ alignof
i alignas
Obsługa wyrównania danych przez kompilator