Prev | Contents | Next

16 <stdalign.h> Macros for Alignment

If you’re coding up something low-level like a memory allocator that interfaces with your OS, you might need this header file. But most C devs go their careers without using it.

Alignment37 is all about multiples of addresses on which objects can be stored. Can you store this at any address? Or must it be a starting address that’s divisible by 2? Or 8? Or 16?

Name Description
alignas() Specify alignment, expands to _Alignas
alignof() Get alignment, expands to _Alignof

These two additional macros are defined to be 1:

__alignas_is_defined
__alignof_is_defined

Quick note: alignments greater than that of max_align_t are known as overalignments and are implementation-defined.

16.1 alignas() _Alignas()

Force a variable to have a certain alignment

Synopsis

#include <stdalign.h>

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

Description

Use this alignment specifier to force the alignment of particular variables. For instance, we can declare c to be char, but aligned as if it were an int:

char alignas(int) c;

You can put a constant integer expression in there, as well. The compiler will probably impose limits on what these values can be. Small powers of 2 (1, 2, 4, 8, and 16) are generally safe bets.

char alignas(8) c;   // align on 8-byte boundaries

For convenience, you can also specify 0 if you want the default alignment (as if you hadn’t said alignas() at all):

char alignas(0) c;   // use default alignment for this type

Example

#include <stdalign.h>
#include <stdio.h>     // for printf()
#include <stddef.h>    // for max_align_t

int main(void)
{
    int i, j;
    char alignas(max_align_t) a, b;
    char alignas(int) c, d;
    char e, f;

    printf("i: %p\n", (void *)&i);
    printf("j: %p\n\n", (void *)&j);
    printf("a: %p\n", (void *)&a);
    printf("b: %p\n\n", (void *)&b);
    printf("c: %p\n", (void *)&c);
    printf("d: %p\n\n", (void *)&d);
    printf("e: %p\n", (void *)&e);
    printf("f: %p\n", (void *)&f);
}

Output on my system follows. Notice the difference between the pairs of values.

i: 0x7ffee7dfb4cc    <-- difference of 4 bytes
j: 0x7ffee7dfb4c8

a: 0x7ffee7dfb4c0    <-- difference of 16 bytes
b: 0x7ffee7dfb4b0

c: 0x7ffee7dfb4ac    <-- difference of 4 bytes
d: 0x7ffee7dfb4a8

e: 0x7ffee7dfb4a7    <-- difference of 1 byte
f: 0x7ffee7dfb4a6

See Also

alignof, max_align_t, memalignment()


16.2 alignof() _Alignof()

Get the alignment of a type

Synopsis

#include <stdalign.h>

alignof(type-name)
_Alignof(type-name)

Description

This evaluates to a value of type size_t that gives the alignment of a particular type on your system.

Return Value

Returns the alignment value, i.e. the address of the beginning of the given type of object must begin on an address boundary divisible by this number.

Example

Print out the alignments of a variety of different types.

#include <stdalign.h>
#include <stdio.h>     // for printf()
#include <stddef.h>    // for max_align_t

struct t {
    int a;
    char b;
    float c;
};

int main(void)
{
    printf("char       : %zu\n", alignof(char));
    printf("short      : %zu\n", alignof(short));
    printf("int        : %zu\n", alignof(int));
    printf("long       : %zu\n", alignof(long));
    printf("long long  : %zu\n", alignof(long long));
    printf("double     : %zu\n", alignof(double));
    printf("long double: %zu\n", alignof(long double));
    printf("struct t   : %zu\n", alignof(struct t));
    printf("max_align_t: %zu\n", alignof(max_align_t));
}

Output on my system:

char       : 1
short      : 2
int        : 4
long       : 8
long long  : 8
double     : 8
long double: 16
struct t   : 16
max_align_t: 16

See Also

alignas, max_align_t, memalignment()


Prev | Contents | Next