int distance(void* first, void* second) { return reinterpret_cast<int>(first) - reinterpret_cast<int>(second); } int main() { alignas(16) int f[4]; alignas(1024) int s[4]; std::cout << distance(f, s); return 0; } 

I just can not understand how alignas() works. Why is the distance equal to 2016, and without it 24?

  • My code doesn't compile at all. Cpp.sh/8igy2 - yrHeTaTeJlb
  • In Visual Studio 2015 works. - Tarakan
  • Very strange numbers. It can be assumed that the debug version is going, and the "extra" bytes on the stack are occupied by guard values, to check for overflowing arrays. - Chorkov
  • You have the UB code, so you can see any numbers. It is impossible to subtract from one pointer another, if they do not point to the same array (or just right behind the array) - ixSci

1 answer 1

alignas is a new thing with a c ++ 11 standard and is intended to fix what is happening in different compilers. Whatever the developers of other languages ​​say, but sometimes you need to write a little bit of low-level code to get a significant plus in speed.

As you know, processors work better with data in memory, if they are aligned on a 4/8/16 byte boundary. And in some cases, the data must be aligned (for example, with some SSE commands and on some ARM processors).

What is border alignment? This is simply an address that is a multiple of a given power of two. That is, address 24 is aligned at the border of 2, 4, 8, but not 16. Address 1024 is aligned with 2, 4, 8, 16, 32, and many others. It can be said in another way - the address aligned on the border 16 in binary form ends with 4 zeros.

alignas just makes the compiler do this alignment. Yes, this often goes to the detriment of memory (voids appear), but in some cases (with SSE) a double increase can be obtained simply because the address is aligned on the 16/32 border. Why it happens? It's simple - modern processors do not load data byte from memory for a long time - they usually load at least 4 bytes at once, moreover, they load at aligned addresses along the border 4. And if you need to load 4 unaligned bytes, then the processor has to do it in three stages - we load the first bytes (but at the same time we load 4 bytes), then we load the second half, and then we add in memory. And since the memory access operation is slow, it lasts long enough.

Do I need to constantly write alignment in my code? No no need. The compilers are smart enough and they can guess. But there are cases when it is better to do.

  • variable is used for SSE / MMX.
  • array variable, of sufficiently large size, which will need to be iterated a lot (run).
  • number crushers.

Why is the distance equal to 2016, and without it 24?

and on ideone in general it turned out -252 :)

alignas says " alignas ", and how exactly to place in memory is another matter. In your case, the compiler first placed the first variable at the address multiple of 16. The second one needs to be placed at the address multiple of 1024. It is logical that this can be done right away (because the first variable takes exactly 16 bytes, and after many, many bytes (we do not know the address of the first variable).

Many compilers in debug mode behind arrays always add a few bytes - in order to prevent the classical output from the array to one element. Therefore, in order to understand why there is 2016, you need to look at the specific version of the compiler and the compilation parameters.