Redigera

Dela via


Alignment (C11)

One of the low-level features of C is the ability to specify the precise alignment of objects in memory to take maximum advantage of the hardware architecture.

CPUs read and write memory more efficiently when they store data at an address that's a multiple of the data size. For example, a 4-byte integer is accessed more efficiently if it's stored at an address that's a multiple of 4. When data isn't aligned, the CPU does more address calculation work to access the data.

By default, the compiler aligns data based on its size: char on a 1-byte boundary, short on a 2-byte boundary, int, long, and float on a 4-byte boundary, double on 8-byte boundary, and so on.

Additionally, by aligning frequently used data with the processor's cache line size, you can improve cache performance. For example, say you define a structure whose size is less than 32 bytes. You may want to use 32-byte alignment to ensure all instances of the structure are cached efficiently.

Usually, you don't need to worry about alignment. The compiler generally aligns data on natural boundaries that are based on the target processor and the size of the data. Data is aligned on up to 4-byte boundaries on 32-bit processors, and 8-byte boundaries on 64-bit processors. In some cases, however, you can achieve performance improvements, or memory savings, by specifying a custom alignment for your data structures.

Use the C11 keyword _Alignof to get the preferred alignment of a type or variable, and _Alignas to specify a custom alignment for a variable or user-defined type.

The convenience macros alignof and alignas, defined in <stdalign.h>, map directly to _Alignof and _Alignas, respectively. These macros match the keywords used in C++. So using the macros instead of the C keywords may be helpful for code portability if you share any code between the two languages.

alignas and _Alignas (C11)

Use alignas or _Alignas to specify custom alignment for a variable or user-defined type. They can be applied to a struct, union, enumeration, or variable.

alignas syntax

alignas(type)
alignas(constant-expression)
_Alignas(type)
_Alignas(constant-expression)

Remarks

_Alignas can't be used in the declaration of a typedef, bit-field, function, function parameter, or an object declared with the register specifier.

Specify an alignment that's a power of two, such as 1, 2, 4, 8, 16, and so on. Don't use a value smaller than the size of the type.

struct and union types have an alignment equal to the largest alignment of any member. Padding bytes are added within a struct to ensure individual member alignment requirements are met.

If there are several alignas specifiers in a declaration (for example, a struct with several members that have differing alignas specifiers), the alignment of the struct will be at least the value of the largest specifier.

alignas example

This example uses the convenience macro alignof because it's portable to C++. The behavior is the same if you use _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 and _Alignof (C11)

_Alignof and its alias alignof returns the alignment in bytes of the specified type. It returns a value of type size_t.

alignof syntax

alignof(type)
_Alignof(type)

alignof example

This example uses the convenience macro alignof because it's portable to C++. The behavior is the same if you use _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
    */
}

Requirements

Compile with /std:c11.

Windows SDK 10.0.20348.0 (version 2104) or later. See Windows SDK to download the latest SDK. For instructions to install and use the SDK for C11 and C17 development, see Install C11 and C17 support in Visual Studio.

See also

/std (Specify Language Standard Version)
C++ alignof and alignas
Compiler handling of data alignment