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, longi 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