Reputation: 20590
// this boxes8a contains a flat array of floats
// There are n boxes and the array is n * 8 long
float* boxes8a = ...;
I want to reinterpret this into an array of Box, where each box contains an array of 4 points. And each point contains 2 floats, (x, y)
struct Box
{
point points[4]
}
struct point
{
float x, y
}
Q1: How do I cast the float* boxes8a
into an array of Box?
Q2: Is it a good practice to do this?
Upvotes: 0
Views: 2093
Reputation: 27577
Q1: how do I cast the float* boxes8a into an array of Box?
Box* boxes = std::reinterpret_cast<Box*>(boxes8a);
Q2: is it good practice to do this?
No, this is an abomination. . It's undefined behaviour. Please redesign your solution to the problem,struct point
can have padding inside or between elements in the array
Upvotes: 0
Reputation: 20396
How do I cast the
float* boxes8a
into an array ofBox
?
Dangerously.
//Undefined Behavior, might not do what you want it to do!
Box* boxes = reinterpret_cast<Box*>(boxes8a);
Is it good practice to do this?
No.
This is considered Undefined Behavior in C++, and while many compilers will give you results that seem like they work if you attempt this, I cannot advise it. Your best solution is to simply copy the values into Box
objects and let the objects own their own data.
std::vector<Box> boxes(n);
for(size_t i = 0; i < n; i++) {
for(int j = 0; j < 4; j++)
boxes[i][j] = point{boxes8a[i*8 + j*2 + 0], boxes8a[i*8 + j*2 + 1]};
}
Alternately, and at the risk of sounding like one of the Data-Oriented-Design Cultists Proponents, you might consider having the Box
object simply contain a pointer to a location in the array where its data begins:
class point {
float* data;
public:
point(float* data) : data(data) {}
float& x() const {return *data;}
float& y() const {return *(data+1);}
};
class Box {
float* data;
public:
Box(float* data) : data(data) {}
point operator[](size_t index) const {
return point(data + index * 2);
}
};
int main() {
std::vector<Box> boxes;
for(size_t i = 0; i < n; i++)
boxes.emplace_back(boxes8a + i*8);
boxes[3][3].x() = 34.7; //Will alter the original value in boxes8a!
}
This method will allow the Box
objects to alias the original float*
array without breaking aliasing rules.
Upvotes: 1
Reputation: 180650
Q1: how do I cast the
float* boxes8a
into an array of Box?
This is not something you should solve by casting. A float*
and a Box
are different things. They both might be built with floats but they are aren't related so can't be cast to each other, as that would be a strict aliasing violation.
Q2: is it good practice to do this?
No. As stated above you aren't allowed to do so.
What you can do though is use std::memcpy
to copy the value of the float
array into the Box
array. That would look like
float* boxes8a = some_data;
Box array[correct_size];
static_asset(sizeof(Box) == sizeof(float) * 8, "data sizes are incompatible");
std::memcpy(array, boxes8a, correct_size);
Upvotes: 3