I work with shared memory right now.
I can't understand alignof
and alignas
.
cppreference is unclear : alignof
returns "alignment" but what is "alignment" ? number of bytes to add for the next block to be aligned ? padded size ? Stack overflow / blogs entries are unclear too.
Can someone explain clearly alignof
and alignas
?
Alignment refers to the arrangement of data in memory, and specifically deals with the issue of accessing data as proper units of information from main memory. First we must conceptualize main memory as a contiguous block of consecutive memory locations. Each location contains a fixed number of bits.
The alignas type specifier is a portable, C++ standard way to specify custom alignment of variables and user defined types. The alignof operator is likewise a standard, portable way to obtain the alignment of a specified type or variable.
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.
In C++11 the alignof operator used to returns the alignment, in bytes of the specified type. Syntax Explanation: alignof: operator returns the alignment in byte, required for instances of type, which type is either complete type, array type or a reference type.
Alignment is a restriction on which memory positions a value's first byte can be stored. (It is needed to improve performance on processors and to permit use of certain instructions that works only on data with particular alignment, for example SSE need to be aligned to 16 bytes, while AVX to 32 bytes.)
Alignment of 16 means that memory addresses that are a multiple of 16 are the only valid addresses.
alignas
force alignment to the required number of bytes. You can only align to powers of 2: 1, 2, 4, 8, 16, 32, 64, 128, ...
#include <cstdlib> #include <iostream> int main() { alignas(16) int a[4]; alignas(1024) int b[4]; printf("%p\n", a); printf("%p", b); }
example output:
0xbfa493e0 0xbfa49000 // note how many more "zeros" now. // binary equivalent 1011 1111 1010 0100 1001 0011 1110 0000 1011 1111 1010 0100 1001 0000 0000 0000 // every zero is just a extra power of 2
the other keyword
alignof
is very convenient, you cannot do something like
int a[4]; assert(a % 16 == 0); // check if alignment is to 16 bytes: WRONG compiler error
but you can do
assert(alignof(a) == 16); assert(alignof(b) == 1024);
note that in reality this is more strict than a simple "%" (modulus) operation. In fact we know that something aligned to 1024 bytes is necessarily aligned to 1, 2, 4, 8 bytes but
assert(alignof(b) == 32); // fail.
So to be more precise, "alignof" returns the greatest power of 2 to wich something is aligned.
Also alignof is a nice way to know in advance minimum alignment requirement for basic datatypes (it will probably return 1 for chars, 4 for float etc.).
Still legal:
alignas(alignof(float)) float SqDistance;
Something with an alignment of 16 then will be placed on the next available address that is a multiple of 16 (there may be a implicit padding from last used address).
Alignment is not padding (although padding is sometimes introduced to satisfy alignment requirements). It is an intrisic property of a C++ type. To put it in standardese (3.11[basic.align]
)
Object types have alignment requirements (3.9.1, 3.9.2) which place restrictions on the addresses at which an object of that type may be allocated. An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated. An object type imposes an alignment requirement on every object of that type; stricter alignment can be requested using the alignment specifier (7.6.2).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With