保证小于int

时间:2018-05-18 14:28:18

标签: c++ bit-fields

我有一个枚举类和以下三个类,我用它来模拟一个特定的(虚构的)cpu。三个POD类对3个不同长度的cpu指令进行建模,包括任何可能的操作数,并且必须分别为1个字节长,2个字节长和4个字节长。

enum class opcode { BRK,  MOV,  LDR, .... etc...};

class op1 {
   unsigned char op;
public:
   constexpr op1(opcode o):op((unsigned char)o) { }
   constexpr opcode get_opcode() const { return (opcode)op; }
};

class op2 {
   unsigned char op;
   signed char operand;
public:
   constexpr op2(opcode o, int v):op((unsigned char)o), operand(v) { }
   constexpr opcode get_opcode() const { return (opcode)op; }
   constexpr int get_operand() const { return operand; }
};

class op3 {
   uint64_t op:8;
   int64_t operand:56;
public:
   constexpr op2(opcode o, int v):op((unsigned char)o), operand(v) { }
   constexpr opcode get_opcode() const { return (opcode)op; }
   constexpr int get_operand() const { return operand; }
};

我确信op1和op2将始终按预期运行,但我担心op3会出现问题。虽然它似乎在我正在开发的平台上正常工作,但我担心因为位域的顺序应该是实现定义的,所以' op' op3的字段将在某些体系结构的内存中处于错误的位置。

我可以将op3的数据布局更改为以下内容以保证成员订单(解决方案1):

class op3 {
   typedef struct { char bytes[7]; } operand_t;
   char op;
   operand_t operand;
public:
...
};

编写构造函数和get_operand成员函数,这些函数访问操作数字段,以这些函数的实现控制的方式对字节进行编码和解码。这样做的另一个好处是能够保证操作数内的特定位顺序,我不会认为这样做会很好。然而,访问速度最终在这里更为重要,所以我想或许这样的事情可能会起作用(解决方案2):

class op3 {
#ifdef OPCODE_FIRST
   uint64_t op:8;
   int64_t operand:56;
public:
   constexpr op2(opcode o, int v):op((unsigned char)o), operand(v) { }
#else
   int64_t operand:56;
   uint64_t op:8;
public:
   constexpr op2(opcode o, int v):operand(v), op((unsigned char)o) { }
#endif
   constexpr opcode get_opcode() const { return (opcode)op; }
   constexpr int get_operand() const { return operand; }
};

当然,我会失去对操作数字段中位的顺序的保证,但至少访问它的代码将是最佳的。

但是,我不确定如何定义OPCODE_FIRST,以便在编译时确定使用哪种结构布局。

因此,简而言之,我更倾向于解决方案1的实现,它可以像访问位域一样可靠地生成最佳代码,但如果这是不可行的,那么解决方案2中的OPCODE_FIRST定义。

或者,也许我还没想到另一种解决方案。

请帮忙。感谢。

编辑:

在解决方案2中,可能会出现以下情况:

struct op3 {
    struct op_first_start {
        std::uint64_t op:8;
        std::int64_t operand:56;
        constexpr op_first_start(opcode o, std::int64_t v):op((int)o),operand(v) { }
    };
    struct op_first_end {
        std::int64_t operand:56;
        std::uint64_t op:8;
        constexpr op_first_end(opcode o, std::int64_t v):operand(v),op((int)o) { }
    };
#if ... ???
    op_first_start data;
#else
    op_first_end data;
#endif
public:
    constexpr op3(int o, std::int64_t v):data(o,v) { }
    constexpr opcode get_op() const { return (opcode)data.op; }
    constexpr std::int64_t get_operand() const { return data.operand; }
};

虽然我仍然不确定我需要在#if条件下放置什么,以使其按预期工作。

我一直在想,而不是预处理器,也许我可以使用像std :: enable_if这样的东西来控制数据的类型' op3中的字段,但我不确定它是如何工作的,或者即使它可以。

0 个答案:

没有答案