这是使用 union 还是 reinterpret_cast 的合适案例
Is this an appropiate case to use 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
被正确初始化,main()
中的 if
语句将是合法的,因为尽管 C++ 的子句 [class.union]/1
中有以下限制标准:
1) In a union, a non-static data member is active if its name refers to an object whose lifetime has begun and has not
ended. At most one of the non-static data members of an object
of union type can be active at any time, that is, the value of at most
one of the non-static data members can be stored in a union at any
time.
以下异常允许您访问公共成员 type
:
One special guarantee is made in order to simplify the use of unions:
If a standard-layout union contains several standard-layout structs
that share a common initial sequence, and if a non-static data
member of an object of this standard-layout union type is active and
is one of the standard-layout structs, it is permitted to inspect the
common initial sequence of any of the standard-layout struct members.
但是你的代码片段中的问题是你创建了一个联合对象 x
而没有激活它的任何成员 ([basic.life]
/1.2):
(...) if the object is a union member or subobject thereof, its
lifetime only begins if that union member is the initialized member in
the union
这意味着当没有成员处于活动状态时,您直接将一些数据读入联合对象,因此仍然没有成员处于活动状态。严格按照标准,我明白这根本不能保证有效。
正确的方法是读取 type
,然后初始化相关成员并读取结构的其余部分(或者将所有内容读入缓冲区并按照类似的策略进行复制).但是,实际上,您的代码将适用于大多数编译器。
我正在从 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
被正确初始化,main()
中的 if
语句将是合法的,因为尽管 C++ 的子句 [class.union]/1
中有以下限制标准:
1) In a union, a non-static data member is active if its name refers to an object whose lifetime has begun and has not ended. At most one of the non-static data members of an object of union type can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.
以下异常允许您访问公共成员 type
:
One special guarantee is made in order to simplify the use of unions: If a standard-layout union contains several standard-layout structs that share a common initial sequence, and if a non-static data member of an object of this standard-layout union type is active and is one of the standard-layout structs, it is permitted to inspect the common initial sequence of any of the standard-layout struct members.
但是你的代码片段中的问题是你创建了一个联合对象 x
而没有激活它的任何成员 ([basic.life]
/1.2):
(...) if the object is a union member or subobject thereof, its lifetime only begins if that union member is the initialized member in the union
这意味着当没有成员处于活动状态时,您直接将一些数据读入联合对象,因此仍然没有成员处于活动状态。严格按照标准,我明白这根本不能保证有效。
正确的方法是读取 type
,然后初始化相关成员并读取结构的其余部分(或者将所有内容读入缓冲区并按照类似的策略进行复制).但是,实际上,您的代码将适用于大多数编译器。