Reputation: 1064
This question is whether casting a byte stream into a non-POD structure is undefined behaviour.
Where data is produced somewhere like this, i.e. packs 4 4-bit values into a short
.
std::vector<unsigned short> v(50);
for(int i<0; k < 50; k++)
{
v[k] = (k%8) | (k+1)%8 << 4 | (k+2)%8 << 8 | (k+2)%8 << 12
}
Then the data is passed to a second module as a byte stream and parsed in the receiving module.
struct Data
{
Data(unsigned short a, unsigned short b, unsigned short c, unsigned short d)
{
value = (a & 0xF) | (b & 0xF) << 4 | (c & 0xF) << 8 | (d & 0xF) << 12
}
Data(unsigned short v) : value(v) {}
short getA() const
{
return value & 0xF
}
short getB() const
{
return (value >> 4) & 0xF
}
short getC() const
{
return (value >> 8) & 0xF
}
short getD() const
{
return (value >> 12) & 0xF
}
private:
unsigned short value;
}
...
unsigned char* data = ...;
Data* ptr = reinterpret_cast<Data*>(data);
ptr[0].getA();
Is this undefined behaviour? The size of the struct Data
is the same as short
, but does the presence of a constructor and member functions make it UB? If I remove the constructors, will it then be fine?
Upvotes: 0
Views: 59
Reputation: 40100
Yes it is. But you can find an easy alternative:
std::vector<unsigned short> in(50);
std::vector<Data> out{begin(in), end(in)};
(void) out[0].getA();
The construction of out
will construct Data
objects in-place from each element of in
. And you can trust your compiler to optimize away any memory copy ;)
Upvotes: 0
Reputation: 31459
You have to go through a constructor to construct an object. You can't simply cast a byte stream and then pretend that it results in a usable object. For a trivially copyable type you can create the object first, then copy in bytes, but otherwise a constructor call is needed.
To answer your question: Yes, that would be UB.
Upvotes: 2