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?
The standard gives little guarantees about memory layout of objects.
For classes/structs:
9.2./15: Nonstatic data members of a class with the same access control are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified. Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions and virtual base classes.
For arrays, the elements are contiguous. Nothing is said about alignment, so it may or may not use same alignment rules than in struct :
8.3.4: An object of array type contains a contiguously allocated non-empty set of N subobjects of type T.
The only thing you can be sure of in your specific example is that a.x
corresponds to arr[0]
, if using a reinterpret_cast:
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 you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With