6

I want to know the alignment guarantees of a statically allocated array of char. Looking at other SO questions, I found some concerning dynamically allocated arrays of char.

For statically allocated char arrays, are they aligned such that I can placement new any type into it (provided it is sufficiently large)? Or does this only apply for dynamically allocated ones?

char buff[sizeof(T)];
T * pT = (T*) buff;
new(pT) T(); // well defined?
...
pT->~T();

If not, how can I overcome this problem?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Thomas Eding
  • 35,312
  • 13
  • 75
  • 106
  • I believe **C++11** guarantees this while **C++03** does not. I will let someone else post an actual answer with quotes from the standard. – K-ballo Jun 26 '12 at 19:31
  • @K-ballo: I don't think C++11 guarantees that. It has added `alignas` for that very purpose. – Nawaz Jun 26 '12 at 19:36
  • @Nawaz: That was my understanding from _3.11/6 [basic.align]_, what do you think? Did I get it wrong? – K-ballo Jun 26 '12 at 19:38
  • @K-ballo: I'm pretty sure you got it wrong. 3.11/6 says that the char types have the weakest alignment, and 3.11/5 says that stricter alignments (with larger alignment values) satisfy weaker alignments (with smaller ones), not the other way around. It boils down to that you can use a char type for an aligned memory area as long as you take care of the alignment. Follow 3.11/6's note's reference to 7.6.2 (the alignment specifier) to see one way of doing that. Another way would be to over allocate the char array, and use an offset pointer inside the array at the appropriate alignment. – James Caccese Jul 16 '12 at 18:36

3 Answers3

11

In C++11, the proper way to do that is this:

char alignas(T) buff[sizeof(T)]; //Notice 'alignas' as
T * pT = (T*) buff;
new(pT) T(); // well defined!

Notice the use of alignas.

If T is a template argument, then it is bettter to use std::alignment_of class template as:

char alignas(std::alignment_of<T>::value) buff[sizeof(T)]; 

Also note that the argument to alignas could be positive integral value Or type. So both of these are equivalent:

char alignas(T)          buff[sizeof(T)];
char alignas(alignof(T))  buff[sizeof(T)]; //same as above

The second one makes use of alignof which returns an integral value of type std::size_t.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 3
    **C+++**, what a nice language would that be! :P – K-ballo Jun 26 '12 at 19:38
  • @Nawaz: K-ballo was (humorously) referring to your "In C+++11" opening remark. – David Hammen Jun 26 '12 at 19:49
  • @DavidHammen: Oops... I didn't notice that. – Nawaz Jun 26 '12 at 19:50
  • @Nawaz, I don't think alignas(T) is the same as alignas(sizeof(T)). For struct for instance, the alignment is the one of the most strictly aligned member, and that is less than the size of the struct for any struct which has more than one members. – AProgrammer Jun 26 '12 at 19:57
  • @AProgrammer: It was a typo. I meant `alignas(alignof(T))` not `alignas(sizeof(T))` – Nawaz Jun 26 '12 at 20:03
  • Why is it better to use `std::alignment_of` than `alignof`. – user1095108 Jul 12 '13 at 21:29
  • 1
    @user1095108: `std::alignment_of` is usually used inside template, in which case if template parameter T is an array type, `std::alignment_of` returns the alignment requirements of the element type. `alignof` doesn't do that. – Nawaz Jul 13 '13 at 00:12
8

If you want to guarantee the alignment of the static char array, you can use the union trick.

union
{
    char buff[sizeof(T)];
    uint64_t dummy;
};

Here the alignment will be guaranteed for the largest element in the union. And of course you should wrap this nastiness away in a nice class.

Edit: better answer:

Of course you'd be even better using boost::aligned_storage or alignas for C++11.

Alex Wilson
  • 6,690
  • 27
  • 44
1

No. Statically allocated arrays are aligned to sizeof(element_type) bytes -- for char it is 1 byte, which basically guarantees no alignment.