这个问题是将字节流强制转换为非POD结构是否是未定义的行为。
在这样的地方生成数据的地方,即将4个4位值打包到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
}
然后将数据作为字节流传递到第二个模块,并在接收模块中进行解析。
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();
这是不确定的行为吗? struct Data
的大小与short
相同,但是是否存在构造函数和成员函数使它成为UB?如果我删除了构造函数,那还好吗?
答案 0 :(得分:2)
您必须通过构造函数构造一个对象。您不能简单地转换一个字节流,然后假装它会导致一个可用的对象。 对于trivially copyable类型,您可以先创建对象,然后以字节为单位进行复制,但是否则需要构造函数调用。
要回答您的问题:是,那就是UB。
答案 1 :(得分:0)
是的。但是您可以找到一个简单的替代方法:
std::vector<unsigned short> in(50);
std::vector<Data> out{begin(in), end(in)};
(void) out[0].getA();
out
的构造将从Data
的每个元素开始就地构造in
对象。并且您可以信任您的编译器以optimize away any memory copy;)