Isolation of a double array into a doubling structure

Is it possible to use a double array for a structure consisting 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"; } 

Prints 1 2 3 . But is it guaranteed to work with any compiler every time?

EDIT: According

9.2.21: Pointer to a standard layout structure object properly converted? using 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 guaranteed work. Right? I understand that many people do not find this aesthetics pleasant, but there are advantages to working with the structure and there is no need to copy the data of the input arrays. I can define the member functions in this structure to calculate scalar and vector products, distances, etc., which will make my code much clearer than if I were working with arrays.

What 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 guaranteed to work, or can the compiler deliver something AFTER the data to sizeof(A) > 3*sizeof(double) ? And is there any portable way to prevent the compiler from doing this?

+8
c ++ arrays language-lawyer struct static-cast
source share
5 answers

No, this is not guaranteed.

The only thing that prohibits any compiler from indenting between x and y , or between y and z , is common sense. There is no rule in any locale that prohibits it.

Even if there is no indentation, even if the representation of A exactly matches the representation of double[3] , then it is still invalid. Language does not allow you to pretend that one type is really another type. You are not even allowed to consider an instance of struct A { int i; }; struct A { int i; }; as if it were struct B { int i; }; struct B { int i; }; .

+8
source share

The standard gives small guarantees regarding the memory location of objects.

For classes / structs:

9.2./15: Non-static members of class data with the same access control are allocated so that later members have higher addresses inside the class object. The distribution order of non-static data members with different access control are not defined. The implementation of the alignment requirement can lead to the fact that immediately two adjacent elements will not be distributed immediately after each other ; therefore the space requirements for managing virtual functions and virtual base classes.

For arrays, elements are adjacent. Nothing is said about alignment, so it may or may not use the same alignment rules as in struct:

8.3.4: An array type object contains an adjacent non-empty set of N subobjects of type T.

The only thing you can be sure of in your specific example is that ax matches arr[0] if reinterpret_cast is used:

9.2.21: A pointer to a standard layout structure object properly converted using reinterpret_cast indicates its initial member (...) and vice versa. [
>

+2
source share

Of all that I know, the answer is yes.

The only thing that can throw you away is the #pragma directive with a very unusual alignment parameter for the structure. If, for example, double types 8 bytes on your computer, and the #pragma directive indicates to align each element to 16-byte boundaries, which can cause problems. Other than that, you're fine.

+1
source share

No, this is not guaranteed, even if it should work with all compilers that I know on common architectures, because the C language specification says:

6.2.6 Representations of types 6.2.6.1 General 1 Representations of all types are not specified, except as indicated in this subclause. And he says nothing about the default replenishment in the structure.

Of course, common architectures use no more than 64 bits, which is twice the size of this architecture, so there should be no additions, and your conversion should work.

But beware : you explicitly call Undefined Behavior, and the next generation of compilers can do something when compiling such a cast.

+1
source share

I do not agree with the consensus here. A structure with three doubles in it is exactly the same as an array with 3 doubles in it. Unless you specifically structure the structure differently and are on a strange processor that has an odd number of bytes to double.

It is not built into the language, but I would feel safe in that. Wise style, I wouldn’t do it, because it was just confusing.

-2
source share

All Articles