我可以使用 union 在各种大小的整数之间进行转换吗?

Can I use union to convert between integers of various size?

让我们考虑一个不同大小的整数并集。是否保证如果一个数字符合每个整数类型的范围,它可以正确地写入和读取任何联合数据成员?

例如此代码

  union U {
    int32_t i;
    int16_t s;
  } u;
  u.s = 1000;
  std::cout<<u.i<<std::endl;

我验证它在一台计算机上正确打印“1000”。它保证在任何其他系统上都能正常工作吗?我想在任何系统上,字节序对于任何整数类型都是相同的,所以问题是联合是否保证将较大整数的较低有效字节用于较小的整数?

我知道这对负数不起作用,所以让我们只考虑非负数。

不,这只适用于小端。在 big endian 中,字节从最重要的位置向下存储。 0xdeadbeef 将在内存中存储为小端 ef be ad de 和内存中的 de ad be ef 大端,因此从起始地址读取 2 个字节将分别导致这些机器中的 0xbeef 和 0xdead

但是你得到了未定义的行为,因为你先写 smaller 2 字节字段然后读取 larger 一个.这意味着 int32_t 的高 2 字节将包含垃圾。这忽略了在 C++ 中使用 union 已经是 UB 的事实。你只能在 C

中这样做

如果您先写入较大的字段然后读取较小的字段,那么它甚至可以用于签名类型:

u.i = -1000;
std::cout << u.s << '\n';

这将在小端机器上按预期打印出来

联合体的大小将始终保持其最大数据成员所必需的大小。

其他数据成员分配在与最大成员相同的字节中。

如何分配 'other members' 的细节由实现定义。根据这个定义,答案是否定的,这不能保证。 参见:https://en.cppreference.com/w/cpp/language/union“解释”

自 C++14 起,联合的所有非静态数据成员将具有相同的地址;但这并没有说明字节序或实现支持。