我有一个枚举类和以下三个类,我用它来模拟一个特定的(虚构的)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中的字段,但我不确定它是如何工作的,或者即使它可以。