Udostępnij za pośrednictwem


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