我目前正在从事一个项目,其中提供了以下内容 结构。我的工作是 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;
根据结构实例的使用方式,所需的字节顺序
该结构可以是大端或小端。作为前两个字节
结构都是单个字节,这些在字节序时不需要改变
变化。
字节 2 和 3,存储为单个 uint16_t
, 是我们唯一需要的字节
交换以实现所需的字节顺序。为了实现字节顺序交换,我们有
一直在执行以下操作:
//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
.我的问题是关于
成员(member)阅读安全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++ union 的非事件成员所引起的未定义行为。
链接草案第 10.4 节的第 1 段还包含以下说明,但我不确定我是否理解所有使用的术语:
[Note: 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 (10.3), and if a non-static datamember of an object of this standard-layout union type is active and is one of the standard-layout structs, itis permitted to inspect the common initial sequence of any of the standard-layout struct members; see 10.3.— end note]
正在阅读myHeader.wId
在 packetIdFlipped = myHeader.wId << 8
行中未定义的行为?
未命名的结构是否是事件成员,因为它是函数调用中写入的最后一个成员?
或者注释是否意味着访问 wId
是安全的?成员,因为它和结构共享一个共同的类型? (这就是通用初始序列的意思吗?)
提前致谢
最佳答案
The function BuildPacketHeader(uint8_t) assigns values to the members wMake and wMod explicitly, and does not write to the member wId. My question is regarding the safety of reading from the member wId inside the returned instance of the structure.
是的,它是 UB。这并不意味着它不起作用,只是它可能不起作用。您可以在 BuildPacketHeader 中使用 memcpy 来避免这种情况(参见 this 和 this)。
关于C++ union 成员访问和未定义行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55281667/