例如,
struct ipv4addr { 联盟{ std :: uint32_t值; std :: uint8_t parts [4]; };};
int main(){ ipv4addr addr; addr.value = …
这很好地定义为fwrite后跟四个get调用来读取它。实际结果取决于机器。在CPU喜欢的任何存储模式下“为我提供uint32的字节”。
共同的初始子序列具有可笑的特定定义。 int 和 struct foo{int x;} 做 的 不 强> 有一个共同的初始子序列。
int
struct foo{int x;}
struct foo{int x;} 和 struct bar{int y;} 确实有一个共同的初始子序列。
struct bar{int y;}
通过不相关的类型读取内存与从联合替代方法中读取内存不同。该文本在那里没有做任何事情。
你可以做 (std::unit8_t const*)&addr.value 并将其视为一个4字节数组,假设您的平台具有 unit8_t 。您获得的字节值是实现定义的。
(std::unit8_t const*)&addr.value
unit8_t
根据标准,你不能从中读取 parts[i] 然而(当价值存在时)。
parts[i]
当标准声明标准未定义时,编译器可以自由指定行为,但在编译期间除外 constexpr 评价。
constexpr
读取最近未分配的联合成员的内容确实是未定义的行为。但是,我使用的大多数编译器都有非标准扩展来允许它。
从技术上讲,如果你希望这是安全的,没有失败的机会,你应该将ip存储为 int32_t 并通过重新解释 reinterpret_cast 读取单个字节,如下所示:
int32_t
reinterpret_cast
int32_t ip = 185734; int8_t *ip_bytes = reinterpret_cast<int8_t*>(&ip). ip_bytes[etc]...
但是,您应该记住,平台的字节顺序将影响任何32位读/写的字节顺序。因此废弃它可能更安全 int32_t 完全想法,只使用一个字节数组。这一切都取决于您需要什么和/或您可能使用的任何库。