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)
{
do
From all I know the answer is: yes.
The only thing that could throw you off is a #pragma directive with some very unusual alignment setting for the struct. If for example a double takes 8 bytes on your machine and the #pragma directive tells to align every member on 16-byte boundaries that could cause problems. Other than that you are fine.
No it is not guaranteed, even if it should work with all compilers I know on common architectures, because C language specification says :
6.2.6 Representations of types 6.2.6.1 General1 The representations of all types are unspecified except as stated in this subclause. And it says nothing on the default padding in a struct.
Of course, common architectures use at most 64bits which is the size of a double on those architecture, so there should be no padding and your conversion should work.
But beware : you are explicitely invoking Undefined Behaviour, and next generation of compilers could do anything when compiling such a cast.
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. [
>
No, it's not guaranteed.
The only thing prohibiting any compiler from inserting padding between x
and y
, or between y
and z
is 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 A
is exactly the same as that of double[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 of struct A { int i; };
as if it's a struct B { int i; };
.
std::complex implementation of msvc use the array solution, and llvm libc++ use the former form.
I think, just check the implementation of the std::complex of your libc++, and use the same solution with it.
I disagree with the consensus here. A struct with three doubles in it, is exactly the same as an array with 3 doubles in it. Unless you specifically pack the struct differently and are on a weird processor that has an odd number of bytes for doubles.
It's not built into the language, but I would feel safe in doing it. Style wise I wouldn't do it, because it's just confusing.