0

I'm using SSE/AVX and I need to store aligned data. how ever, my data can be of different types. so I use a union like this

union Data
{
    bool Bools[128];
    int32 Ints32[128];
    int64 Ints64[128];
    // ... other data types
} data;

Can I do the following?

union alignas(16) Data
{
    alignas(4) bool Bools[128];
    alignas(4) int32 Ints32[128];
    alignas(8) int64 Ints64[128];
    alignas(16) Bar Bars[128]; // Bar is 16 bytes
} data;

so I expect Ints32 and Bool elements to be aligned as 4 bytes, yet Int64 elements are aligned as 8 bytes.

because of Bar first element of each array (or basically &data) should also be aligned to 16 bytes. but elements of each array should be aligned as stated. so is my union correct?

timrau
  • 22,578
  • 4
  • 51
  • 64
M.kazem Akhgary
  • 18,645
  • 8
  • 57
  • 118
  • sizeof(bool) could be 1. In that case, even if you got your Bools array aligned to a 4 byte boundary, that would only be for the first (and then every 4th) entry. The other array elements would (mostly) not be so aligned. Doing so would break pointer arithmetic, a fundamental part of the language. If you need elements of the Bools array to be 4 bye aligned, you will need to change it to be an array of something with a size of (a multiple of ) 4 bytes. – Avi Berger Jan 24 '23 at 19:55
  • if Data is bool, it's never gonna change to another type (same for other types too). but I'm using union to reduce the amount of code and also avoid virtual functions or inheritance. I'm not sure what you mean about breaking pointer arithmetic. @AviBerger – M.kazem Akhgary Jan 24 '23 at 20:11
  • Forgetting about unions for this - not relevant to my point. If sizeof(bool) is 1 on your platform and you have an array `alignas(4) bool Bools[128];` Then the array Bools has 4-byte alignment. As a consequence, Bools[0] (Bools[4], Bools[8], . . . ) will be 4-byte aligned. The other elements of Bools will not be so aligned. If Bools is located at address 100, addresses will be Bools[0] : 100; Bools[1] : 101; Bools[2] : 102; Bools[3]: 103; etc. Arrays and pointer arithmetic were set up to function consistently together. . . . – Avi Berger Jan 24 '23 at 20:40
  • 1
    . . . Increasing the array index increases the memory address by sizeof( array element) bytes. So does adding 1 to a pointer to an array element. They degenerate to the same code and the stride is fixed at sizeof(element type) bytes. You can align the array. You can't inject padding between array elements. You could change the array element type to something of the appropriate size (perhaps int32_t) as a stand in. – Avi Berger Jan 24 '23 at 20:40
  • @AviBerger Thanks, now I understand what you mean, basically I can store booleans as integers for the right padding. – M.kazem Akhgary Jan 24 '23 at 22:43

1 Answers1

2

The alignment specifier applies only to the entity it defines. It applies to the whole class (union) object's alignment or the alignment of the individual arrays. It never applies to elements of the array.

The alignment of elements in an array of type T can never be guaranteed to be stricter than the size of T, because elements of an array must be allocated contiguously in memory without padding. This is for example necessary so that pointer arithmetic can work. The type of the member doesn't include any information about the alignment specifier you used, so e.g. evaluating Bools[i] must be sure how far apart individual elements of type bool and can't adjust to alignment specifiers.

If you want to adjust element-wise alignment then you need to specify your own type with the required alignment and form an array of that type.

Because the initial address of the subobjects of a union has to be equal to that of the union object itself, there is also no point to add weaker alignment specifiers to the subobjects. They can't have any effect.

user17732522
  • 53,019
  • 2
  • 56
  • 105
  • ok so ignoring `bool` case, I can just do `union alignas(16) Data` and everything is aligned as expected. except for bool, but I think i can get away with that case. – M.kazem Akhgary Jan 24 '23 at 22:39
  • AviBerger also suggested storing bool as integer for that matter. thanks for answer. – M.kazem Akhgary Jan 24 '23 at 22:44
  • 1
    @M.kazemAkhgary No, that applies to all types. None of the `alignas` will cause any of the array elements (except the first) to be aligned any stricter than their size. It is impossible to change the alignment of the other elements without changing their type. – user17732522 Jan 24 '23 at 23:54