For example I have this struct
struct A {
float x;
float y;
float z;
};
Can I do this? A a; float* array = (float*)&a;
And use a as float array?
For example I have this struct
struct A {
float x;
float y;
float z;
};
Can I do this? A a; float* array = (float*)&a;
And use a as float array?
No, typecasting a struct
to an array will not work. Compilers are allowed to add padding between members.
Arrays have no padding between members.
Note: there is nothing stopping you from casting, however, using value after cast results in undefined behavior.
In a practical sense, yes you can do that and it will work in all the mostly used architectures and compilers.
See "Typical alignment of C structs on x86" section on Wikipedia.
More details:
floats are 4 bytes and no padding will be inserted (in practically all cases).
also most compilers have the option to specify the packing of structures and you can enforce that no padding is inserted( i.e. #pragma pack from visual studio )
arrays are guarantied to be contiguous in memory.
Can you guarantee that it will work in all CPUs in the world with all the compilers? No.. but I would definitely like to see a platform where this fails :)
EDIT: adding static_assert(sizeof(A) == 3*sizeof(float))
will make this code not compile if there are padding bytes. So then you'll be sure it works when it compiles.
This is a strict aliasing violation, plain and simple. Any access with that pointer, to any element but the first, is undefined behavior in your case. And in more complex cases it's just plain undefined behavior regardless of which element you access.
If you need an array, use an array. std::array
also has an overload for for std::get
, so you can use that to name each individual array member:
using A = std::array<float, 3>;
enum AElement { X, Y, Z };
int main() {
A a;
get<X>(a) = 3.0f; // sets X;
float* array = a.data(); // perfectly well defined
}
For g++ you can use attribute for your struct, like this:
struct A {
float x;
float y;
float z;
}__attribute__((__packed__));
It's disable struct alignment.
You can do that, until the compiler starts optimising, and then things go wrong.
Accessing any but the first element of a struct by using a pointer to the first element is undefined behaviour. "Undefined behaviour" means that anything can happen. The compiler may assume that there is no undefined behaviour.
There are many consequences that the compiler can deduce from that: If the compiler knows that your float* points to the first element of the struct, then it can deduce that every index to that array equals 0 (because anything else is undefined behaviour). If the compiler doesn't know this, then it can deduce that the array pointer cannot point to the struct, and changing array elements can't change struct elements and vice versa.
Can you see how this will go wrong?