Is it OK to cast a double array to a struct made of doubles?
struct A
{
   double x;
   double y;
   double z;
};
int main (int argc , char ** argv)
{
   double arr[3] = {1.0,2.0,3.0};
   A* a = static_cast<A*>(static_cast<void*>(arr));
   std::cout << a->x << " " << a->y << " " << a->z << "\n";
}
This prints 1 2 3. But is it guaranteed to work every time with any compiler?
EDIT: According to
9.2.21: A pointer to a standard-layout struct object, suitably converted ? using a reinterpret_cast, points to its initial member (...) and vice versa.
if I replace my code with
struct A
{
  double & x() { return data[0]; }
  double & y() { return data[1]; }
  double & z() { return data[2]; }
private:
   double data[3];
};
int main (int, char **)
{
   double arr[3] = {1.0,2.0,3.0};
   A* a = reinterpret_cast<A*>(arr);
   std::cout << a->x() << " " << a->y() << " " << a->z() << "\n";
}
then it is guaranteed to work. Correct? I understand that many people would not find this aesteticaly pleasing but there are advantages in working with a struct and not having to copy the input array data. I can define member functions in that struct to compute scalar and vector products, distances etc, that will make my code much easier to understand than if I work with arrays.
How about
int main (int, char **)
{
   double arr[6] = {1.0,2.0,3.0,4.0,5.0,6.0};
   A* a = reinterpret_cast<A*>(arr);
   std::cout << a[0].x() << " " << a[0].y() << " " << a[0].z() << "\n";
   std::cout << a[1].x() << " " << a[1].y() << " " << a[1].z() << "\n";
}
Is this also guaranteed to work or the compiler could put something AFTER the data members so that sizeof(A) > 3*sizeof(double)? And is there any portable way to prevent the compiler from doing so?
                        
No, it's not guaranteed.
The only thing prohibiting any compiler from inserting padding between
xandy, or betweenyandzis common sense. There is no rule in any language standard that would disallow it.Even if there is no padding, even if the representation of
Ais exactly the same as that ofdouble[3], then it's still not valid. The language doesn't allow you to pretend one type is really another type. You're not even allowed to treat an instance ofstruct A { int i; };as if it's astruct B { int i; };.