24

Suppose I have some type T that has to be N bytes aligned. Now I declare an array of type T:

T array[size];

Will the array have the same alignment requirements as type T or will it have any other alignment requirements?

masoud
  • 55,379
  • 16
  • 141
  • 208
sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 2
    I'm curious, why does it matter? – Pubby Nov 08 '12 at 07:18
  • 2
    @Pubby: I'm reviewing code and I've found some rather curious comment about arrays and alignment requirements and I'm almost sure that comments is blsht, but want to verify. – sharptooth Nov 08 '12 at 07:22

4 Answers4

19

Yes, the alignment requirements must be the same. Obviously an array of T must be aligned at least as strictly as a single T otherwise its first member would not be properly aligned. The fact that an array cannot be more strictly aligned than its element type follows from the standard section 8.3.4 which says that arrays are contiguously allocated element subobjects. Consider this array of arrays:

T a[2][size];

Whatever the value of size, there can be no "extra" padding between the two arrays a[0] and a[1] otherwise this violates the contiguosly allocated requirement.

Equivalently, we know that (char*)&a[1] == (char*)&a[0] + sizeof(a[0]) and sizeof(a[0]) == sizeof(T[size]) == size * sizeof(T). As this holds for any size it must be possible to place an array of T at any address which is suitably aligned for a single T object (given adequate address space).

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • From what I understand, if the size of the sub-array is a multiple of the alignment then the alignment could be different from the element's as no padding would be required. [This comment](http://stackoverflow.com/users/147192/matthieu-m) seems to be the correct answer. – Pubby Nov 08 '12 at 07:57
  • [Whoops, this link](http://stackoverflow.com/questions/13284208/how-is-an-array-aligned-in-c-compared-to-a-type-contained/13284631#comment18111863_13284297) – Pubby Nov 08 '12 at 08:09
  • 1
    `T[2]` could be aligned to `alignof(T) * 2` which would allow `T[2][size]` to not have any padding. – Pubby Nov 08 '12 at 08:10
  • @Pubby: So basically you're saying my argument is bogus because some arrays might have stricter alignment than other arrays? – CB Bailey Nov 08 '12 at 08:16
  • 2
    The use of the _contiguously allocated_ requirement and multiple dimension arrays is an interesting argument; it hadn't occurred to me. I'm always a bit suspicious of such indirect arguments, but in this case, I don't think it makes a difference: I suspect that if the committee didn't explicitly ban requiring stricter alignment, it's probably because it didn't occur to them that the case could exist. – James Kanze Nov 08 '12 at 08:29
  • 1
    When applied to a class, the result is the number of bytes in an object of that class including any padding required for placing objects of that type in an array. § 5.3.3/2 Sizeof n4606 – Michael Marcin Oct 20 '16 at 06:42
4

The array's alignment requirements will be identical to those of the array elements, I believe.

Obviously, the start of the array must be aligned at least as strictly as its first element requires, so its alignment requirements can't be less strict.

The start address of the array plus the size of each element must leave the second element sufficiently aligned. That places a constraint on the size of the element type, which I believe means padding can be introduced at the end of a structure just to keep arrays aligned, even if you never use that struct in an array. But it does not mean there's any need for stricter alignment.

By induction, subsequent elements are OK if the first two are OK, so giving the array the same alignment requirements as its elements should be fine.

A citation from the spec would be nice, though.

Jamey Sharp
  • 8,363
  • 2
  • 29
  • 42
  • 8
    Here you go (for alignment) **§5.3.6 [expr.alignof]** 1/ An `alignof` expression yields the alignment requirement of its operand type. The operand shall be a *type-id* representing a complete object type or an array thereof [...] 3/ [...] When `alignof` is applied to an array type, the result shall be the alignment of the element type. – Matthieu M. Nov 08 '12 at 07:51
  • Any "padding" must be reflected in the `sizeof`; an element not in an array must have the same size as one not in the array. As for the second point, I don't think the standard denies arrays the right to have stricter alignment requirements than non-array types (I'm fairly sure with regards to C++03, which doesn't say much about alignment to begin with), but in practice, the alignment requirements will be the same. – James Kanze Nov 08 '12 at 08:20
  • The alignment requirements will be the same, with one noticeable exception. The return value of a `new char[n]` (where `char` can in fact be any character type) must be sufficiently aligned for any type which can fit in `n`. Note, however, that this guarantee _only_ applies to `new` expressions; it does not apply to variables of type `char[]`. – James Kanze Nov 08 '12 at 08:24
1

The rules are the same i believe but the interpretation might be confusing.

I believed since each element of array would be of the same size so only aligning the first element would automatically align the rest and hence there would never be any padding between elements.

This might be true in case of a trivial array but not for complex scenarios.

The stride of an array can be large than element size i.e. there could be pads between each individual elements.

Following is a good example

struct ThreeBytesWide {
    char a[3];
};

struct ThreeBytesWide myArray[100];

source - stride wikipedia

Each element of ThreeBytesWide array could be aligned to four byte boundary

Edit: As elaborated in the comments, the mention of having pads between individual elements is when the element itself is say 3 bytes and aligned to four byte boundary.

fkl
  • 5,412
  • 4
  • 28
  • 68
  • That article is misleading, as sources on C/C++ behavior go. From its Talk page: "the "stride" and sizeof() in C and C++ are always the same, that is sizeof(T[N]) == sizeof(T) * N. See for example 8.3.4 of ISO14882:2003(e) or 6.5.2.1 of ISO9899:1999(e) as well as 6.5.6 of ISO9899:1999(e) and 6.2.5-20 of ISO9899:1999(e). Also 6.5.3.4-6 of ISO9899:1999(e) is intresting here." – Jamey Sharp Nov 08 '12 at 07:35
  • There is no padding in the array(s). If the struct is aligned at a four byte boundary, we would also have `sizeof(ThreeBytesWide)== 4` with an unused byte at the end of each struct. – Bo Persson Nov 08 '12 at 07:45
  • I am not sure i fully understand both comments. @BoPersson i was also saying that the sizeof(ThreeBytesWide) would be 4. So for an individual array there won't be padding except the first byte unless it is packed in a struct like done above. – fkl Nov 08 '12 at 07:49
  • 2
    @fayyazkl - The protests are against "there could be pads between each individual elements". There can never be padding *between* the members of an array, they are always exactly `sizeof(element)` apart. If there is any padding, it would have to be inside each array element, not between them. – Bo Persson Nov 08 '12 at 12:01
  • 1
    @BoPersson reviewing my answer above again, i feel what i wrote was saying "there can never be pads between array elements. The example i showed is a scenario which might mislead one to think it was otherwise, but it is actually pad inside each struct element already. For the array, it is still an element of size 4 bytes each" I am considering improving my wordings since what i see above is essentially the same – fkl Nov 08 '12 at 12:11
0

An array of objects is required to be contiguous, so there's never padding between the objects, though padding can be added to the end of an object (producing nearly the same effect). C++ Data Member Alignment and Array Packing

#include <iostream>

__declspec(align(32)) 
struct Str1
{
   int a;
   char c;
}; 

template<typename T>
struct size
{
    T arr[10];
};


int main()
{
    size<Str1> b1;

    std::cout << sizeof(Str1) << std::endl; //  prints 32
    std::cout << sizeof(b1) << std::endl;   //  prints 320

    std::cin.ignore();
    return 0;
}

References:

  1. Data alignment in C++, standard and portability
  2. http://msdn.microsoft.com/en-us/library/83ythb65.aspx
Community
  • 1
  • 1
Sarang
  • 1,867
  • 1
  • 16
  • 31