【发布时间】:2019-08-12 09:08:30
【问题描述】:
我目前正在从事一个项目,在该项目中我获得了以下信息 结构。我的工作是 C++,但该项目同时使用 C 和 C++。相同的结构 C 和 C++ 都使用定义。
typedef struct PacketHeader {
//Byte 0
uint8_t bRes :4;
uint8_t bEmpty :1;
uint8_t bWait :1;
uint8_t bErr :1;
uint8_t bEnable :1;
//Byte 1
uint8_t bInst :4;
uint8_t bCount :3;
uint8_t bRres :1;
//Bytes 2, 3
union {
uint16_t wId; /* Needed for Endian swapping */
struct{
uint16_t wMake :4;
uint16_t wMod :12;
};
};
} PacketHeader;
根据结构实例的使用方式,所需的字节序
结构可以是大端或小端。作为前两个字节
结构是每个单个字节,这些不需要在字节序时改变
变化。
存储为单个uint16_t 的字节 2 和 3 是我们需要的唯一字节
交换以实现所需的字节顺序。为了实现字节顺序交换,我们有
一直在执行以下操作:
//Returns a constructed instance of PacketHeader with relevant fields set and the provided counter value
PacketHeader myHeader = mmt::BuildPacketHeader(count);
uint16_t packetIdFlipped;
//Swap positions of byte 2 and 3
packetIdFlipped = myHeader.wId << 8;
packetIdFlipped |= (uint16_t)myHeader.wId >> 8;
myHeader.wId = packetIdFlipped;
函数BuildPacketHeader(uint8_t) 将值分配给成员wMake 和
明确地wMod,并且不写信给成员wId。我的问题是关于
从返回的实例中的成员 wId 读取的安全性
结构。
诸如此类的问题 Accessing inactive union member and undefined behavior?, Purpose of Unions in C and C++, 和Section 10.4 of the draft standard I have 都提到了在 C++ 中访问联合的非活动成员所产生的未定义行为。
链接草案第 10.4 节中的第 1 段还包含以下注释,但我不确定我是否理解所有使用的术语:
[注意:为了简化联合的使用,我们做了一个特殊的保证:如果一个标准布局联合包含几个共享一个公共初始序列(10.3)的标准布局结构,并且如果一个非静态数据成员此标准布局联合类型的对象是活动的并且是标准布局结构之一,允许检查任何标准布局结构成员的公共初始序列;见 10.3.- 尾注]
是否在packetIdFlipped = myHeader.wId << 8 行中读取myHeader.wId 未定义的行为?
未命名的结构是否是活动成员,因为它是函数调用中写入的最后一个成员?
或者注释是否意味着访问wId 成员是安全的,因为它和结构共享一个公共类型? (这就是通用初始序列的意思吗?)
提前致谢
【问题讨论】:
-
匿名结构在 C++ 中的格式不正确。 IE。这个:
struct{ /* members */ }; -
@eerorika 谢谢 - 我什至没有意识到这一点。调查它导致我发表评论 类似于 union,一个未命名的结构成员,其类型是一个没有名称的结构,称为匿名结构。匿名结构的每个成员都被认为是封闭结构或联合的成员。如果封闭的结构或联合也是匿名的,这将递归地应用 here。这是否意味着上面的代码实际上 不是 UB,因为内部结构和联合的每个成员都被视为
struct PacketHeader的成员? -
是UB。匿名的工会不会改变任何事情。
-
似乎找不到编辑评论按钮,但仔细阅读后,我认为该链接无论如何都是指 C。非常感谢,再次
标签: c++ language-lawyer undefined-behavior unions