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-bajtowej itd.
Ponadto dzięki dopasowaniu często używanych danych do rozmiaru 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-bajtowego, aby zapewnić wydajne buforowanie wszystkich wystąpień struktury.
Zazwyczaj nie trzeba martwić się o wyrównanie. Kompilator zazwyczaj 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 8-bajtowych granic procesorów 64-bitowych. W niektórych przypadkach jednak można osiągnąć poprawę wydajności lub oszczędność pamięci, określając niestandardowe wyrównanie dla 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>
metodzie , są mapowane bezpośrednio na _Alignof
elementy i _Alignas
. 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ępnisz dowolny kod między dwoma językami.
alignas
i _Alignas
(C11)
Służy alignas
do _Alignas
określania niestandardowego wyrównania 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żywać 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 elemencie 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
obiektu będzie co najmniej wartością największego specyfikatora.
alignas
Przykład
W tym przykładzie użyto makra alignof
wygody, ponieważ jest przenośne do języka 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
i 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 przenośne do języka 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 przy użyciu 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 W11 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
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla