Consider the following:
#include <vector>
using namespace std;
struct Vec2
{
float m_x;
float m_y;
};
vector<Vec2> myArray;
int main()
{
myArray.resize(100);
for (int i = 0; i < 100; ++i)
{
myArray[i].m_x = (float)(i);
myArray[i].m_y = (float)(i);
}
float* raw;
raw = reinterpret_cast<float*>(&(myArray[0]));
}
Is raw guaranteed to have 200 contiguous floats with the correct values? That is, does the standard guarantee this?
EDIT: If the above is guaranteed, and if Vec2 has some functions (non-virtual) and a constructor, is the guarantee still there?
NOTE: I realize this is dangerous, in my particular case I have no choice as I am working with a 3rd party library.
I realize this is dangerous, in my particular case I have no choice as I am working with a 3rd party library.
You may add compile time check of structure size:
live demo
struct Vec2
{
float a;
float b;
};
int main()
{
int assert_s[ sizeof(Vec2) == 2*sizeof(float) ? 1 : -1 ];
}
It would increase your confidence of your approach (which is still unsafe due to reinterpret_cast, as mentioned).
raw = reinterpret_cast(&(myArray[0]));
ISO C++98 9.2/17:
A pointer to a POD struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa. [ Note: There might therefore be unnamed padding within a standard-layout struct object, but not at its beginning, as necessary to achieve appropriate alignment. —end note ]
And finally, runtime check of corresponding addresses would make such solution rather safe. It can be done during unit-tests or even at every start of program (on small test array).
Putting it all together:
live demo
#include <vector>
#include <cassert>
using namespace std;
struct Vec2
{
float a;
float b;
};
int main()
{
int assert_s[ sizeof(Vec2) == 2*sizeof(float) ? 1 : -1 ];
typedef vector<Vec2> Vector;
Vector v(32);
float *first=static_cast<float*>(static_cast<void*>(&v[0]));
for(Vector::size_type i,size=v.size();i!=size;++i)
{
assert((first+i*2) == (&(v[i].a)));
assert((first+i*2+1) == (&(v[i].b)));
}
assert(false != false);
}
No, this is not safe, because the compiler is free to insert padding between or after the two floats in the structure, and so the floats of the structure may not be contiguous.
If you still want to try it, you can add compile time checks to add more surety that it will work:
static_assert(sizeof(Vec2) == sizeof(float) * 2, "Vec2 struct is too big!");
static_assert(offsetof(Vec2, b) == sizeof(float), "Vec2::b at the wrong offset!");
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