std::array
is ... (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 adress of an array is always the same as the adress of its first element, ie 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]; }
CodePudding user response:
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.