Search code examples
c++language-lawyerstdarray

Is the address of a std::array guaranteed the same as its data?


std::array is ... (quoting from cppreference):

This container is an aggregate type with the same semantics as a struct holding a C-style array T[N] as its only non-static data member.

Does that imply that the address of an array is always the same as the address of its first element, i.e. data()?

#include <array>
#include <iostream>

int main()
{
    std::array<int,6> x{};
    std::cout << &x << "\n";
    std::cout << x.data();
}

Possible output:

0x7ffc86a62860
0x7ffc86a62860

And if yes, is this of any use? Is the following allowed?

int* p = reinterpret_cast<int*>(&x);
for (int i=0;i<6;++i){ std::cout << p[i]; }

Solution

  • Technically, a std::array object may have padding at the beginning, in which case the data will be at a higher address than the std::array object. Only for standard-layout classes is there a guarantee that the object itself has the same address as the first non-static data member.

    There is no guarantee in the standard that std::array<T, N> is standard-layout, even if T is int or something like that. All reasonable implementations of std::array<T, N> will have a single non-static data member of type T[N], no virtual functions, and at most a single inheritance chain with no virtual base classes, which would mean they would be standard-layout as long as T itself is standard-layout. Plus, even if T is not standard-layout, the compiler is not likely to insert padding at the beginning of the std::array object.

    So, while an assumption that a std::array<T, N> object has the same address as the first T object it contains is not portable, it is basically guaranteed in practice. And you can add a static_assert(sizeof(std::array<T, N>) == sizeof(T[N])); just to be sure that, if someone ever tries to build your code on an exotic implementation where it isn't the case, they'll know it's not supported.