C++ 将 int 转换为枚举,然后将该枚举读取为位字段安全与否?

问题描述 投票:0回答:1
#include <iostream>
#include <stdio.h>
#include <string>
#include <cstring>
using namespace std;

enum class OrderFlags : uint16_t {
  None = 0,
  BuySide = 1,
  UpdateVolume = 2,
  UpdatePrice = 4,
  Market = 8,
  Float = 16,
  Aggressive = 32,
};

struct OrderFlagsBitField {
  uint8_t side : 1;
  uint8_t update_volume : 1;
  uint8_t update_price : 1;
  uint8_t market_order : 1;
  uint8_t float_order : 1;
  uint8_t aggressive : 1;
  uint16_t reserved : 10;
};
static_assert(sizeof(OrderFlagsBitField) == 2);

struct Order {
    int order_id;
    union {
        OrderFlags flags;
        OrderFlagsBitField flags_bf;
    };
};

int main()
{
    Order order1;
    order1.order_id = 123;
    uint16_t value = 1 + 2 + 8 + 32;
    memcpy(&order1.flags, &value, sizeof(value));

    Order order2 = order1;
    cout << int(order2.flags_bf.side) << " " << int(order2.flags_bf.update_volume) << " " << int(order2.flags_bf.update_price) << " "
         << int(order2.flags_bf.market_order) << " " << int(order2.flags_bf.float_order) << " " << int(order2.flags_bf.aggressive) << "\n";
    return 0;
}

我有一个像上面这样的代码。

value
表示可以包含多个
OrderFlags
值的标志。基本上,我想用这个联合将
uint16_t
序列化为
Order
对象。

这个代码安全吗?对于这种情况,输出应该是

1 1 0 1 0 1
,即使我将
order1
对象写入文件,然后再次从该文件读取字节到
order2

c++ serialization enums union undefined-behavior
1个回答
0
投票

这是未定义的行为。改为处理位字段中的每个标志。如:

int bf2int(BitFieldFlag flag)
{
  int res = 0;
  if (flag.attribute1) res |= 1 << 0;
  if (flag.attribute2) res |= 1 << 1;
  // ...
  return res;
}

void int2bf(BitFieldFlag &flag, int flag_int)
{
  memset(&flag, 0, sizeof(flag));
  if ((flag_int >> 0) & 1) flag.attribute1 = 1;
  if ((flag_int >> 1) & 1) flag.attribute2 = 1;
  // ...
}
© www.soinside.com 2019 - 2024. All rights reserved.