c++ - 这是使用 union vs reinterpret_cast 的合适案例吗
问题描述
我正在从 io 设备接收四个字(32 位)的数据。消息中的第一个词告诉我传入的数据是什么。我想知道这是否是使用 union 或 reinterpret_cast 的情况。
这是我的用例...
struct Plain {
uint32_t type;
uint32_t data1;
uint32_t data2;
uint32_t data3;
}
struct Special1 {
uint32_t type;
uint32_t data1;
float data2;
uint32_t data3;
}
struct Special2 {
uint32_t type;
uint32_t data1;
float data2;
uint16_t data3;
uint16_t data4;
}
union My_union {
Plain p1;
Special1 p2;
Special2 p3;
}
void foo(const Special1& x);
void foo(const Special2& x);
int main() {
My_union x;
read(&x.p1, sizeof(Plain)); // read from an IO device
if(x.p1.type == 1)
{
foo(x.p2);
}
else
{
foo(x.p3);
}
return 0;
}
我试图弄清楚这是否是使用工会的合适案例,或者演员仍然是要走的路,如果是,为什么?
解决方案
如果对象x
被正确初始化,则if
in 中的语句main()
将是合法的,因为尽管[class.union]/1
C++ 标准的条款中有以下限制:
1)在联合中,如果一个非静态数据成员的名称引用了一个生命周期已经开始但尚未结束的对象,则它是活动的。union 类型的对象的非静态数据成员在任何时候最多可以有一个是活动的,即在任何时候最多可以将一个非静态数据成员的值存储在一个 union 中。
以下异常允许您访问公共成员type
:
一个特殊的保证是为了简化联合的使用:如果一个标准布局联合包含几个共享一个公共初始序列的标准布局结构,并且如果这个标准布局联合的对象的一个非静态数据成员type 是活动的并且是标准布局结构之一,它允许检查任何标准布局结构成员的公共初始序列。
但是您的代码段中的问题是您创建了一个联合对象x
而不激活其任何成员([basic.life]
/1.2):
(...) 如果对象是联合成员或其子对象,则它的生命周期仅在联合成员是联合中的初始化成员时才开始
这意味着当没有成员处于活动状态时,您直接将一些数据读入联合对象,因此仍然没有成员处于活动状态。严格遵循标准,我知道这根本不能保证有效。
正确的方法是读取type
,然后初始化相关成员并在其中读取结构的其余部分(或将所有内容读入缓冲区并按照类似策略进行复制)。但是,实际上,您的代码将适用于大多数编译器。
推荐阅读
- c# - 在 C# 应用程序中收到编组结构后不久堆损坏
- git - 在jenkins中禁用项目会停止wehbhoot触发器吗?
- powershell - 多个 Get-WmiObject 调用的单一连接
- swift - ARSCNView 在 iOS 12 上因 GPU 错误“命令缓冲区的执行被中止...(IOAF 代码 5)”而滞后
- julia - Julia:“<:”符号是什么意思?
- hugo - 为什么我的 Hugo 站点在部署到 Netlify 时不显示?
- python-2.7 - Flask 使用请求将上传的文件传递给另一个服务
- python - 如何在 for 循环中构建具有 NN 层的 TensorFlow 图?
- javascript - React 中的属性“displayName”是什么?未捕获的类型错误:无法读取 null 的属性“displayName”
- motorola - 为什么摩托罗拉68k的32位通用寄存器分为数据寄存器和地址寄存器?