在C++中切割位

And*_*dro 7 c c++

假设我们有一个包含32位数字的二进制文件.每个32位数字代表一条指令.我的问题:是否可以直接将这些位切成6 + 5 + 5 + 16的块.就像是:

typedef struct _instruction
{
    int op_code : 6;
    int reg_dest : 5;
    int reg_s1 : 5;
    int offset : 16;
} INST, *PINST;

int read_32_bits = read_next_instr();

INST i = (INST)read_32_bit; /* this would cut the bits into chunks*/
Run Code Online (Sandbox Code Playgroud)

小智 6

为什么不像你一样创建一个比特结构,然后把它放在一个联盟里?我删除了typedef,因此它使用C++样式定义.

struct instruction
{
    int op_code  : 6;
    int reg_dest : 5;
    int reg_s1   : 5;
    int offset   :16;
};

union INST
{
    instruction  a;
    uint32_t     b;
};
Run Code Online (Sandbox Code Playgroud)

您可以使用网络功能存储/加载32位值:

INST  i;
i.b = ntohl(value);
Run Code Online (Sandbox Code Playgroud)

现在,您可以在不进行类型转换的情况下引用位字段.

if (i.a.op_code == XXX)
Run Code Online (Sandbox Code Playgroud)


Omn*_*ous 3

这是一个可行的答案,可移植,不会在任何编译器上调用未定义的行为,并且可以相当有效地优化:

struct instruction {
   typedef unsigned int uint_t;

   explicit instruction(uint_t val) : val_(val) {}
   instruction(uint_t op_code, uint_t reg_dest, uint_t reg_s1, uint_t offset)
     : val_((op_code & 0x3fu << 26) | (reg_dest & 0x1fu << 21) |
            (reg_s1 & 0x1fu << 16) | (offset & 0xffffu))
   {
   }

   uint_t op_code() const { return (val_ >> 26) & 0x3fu; }
   void op_code(uint_t newval) { val_ = (newval & 0x3fu << 26) | (val_ & 0x3ffffffu); }

   uint_t reg_dest() const { return (val_ >> 21) & 0x1fu; }
   void reg_dest(uint_t newval) { val_ = (newval & 0x1fu << 21) | (val_ & 0xfc1fffffu); }

   uint_t reg_s1() const { return (val_ >> 16) & 0x1fu; }
   void reg_s1(uint_t newval) { val_ = (newval & 0x1fu) << 16) | (val_ & 0xffe0ffffu); }

   uint_t offset() const { return (val_ >> 16) & 0xffffu; }
   void offset(uint_t newval) const { val_ = (newval & 0xffffu) | (val & 0xffff0000u); }

   uint_t &int_ref() { return val_; }
   uint_t int_ref() const { return val_; }

 private:
   uint_t val_;
};
Run Code Online (Sandbox Code Playgroud)

这使您可以使用非常方便的符号访问所有位字段。我认为它也是一个 POD,可以让您以一些有趣的方式使用它。一个好的编译器将在优化位修改操作方面做得相当不错,特别是当您连续多次调用便利函数时。

它几乎与具有覆盖位字段一样好。首先需要做更多的定义工作。

另外,我将类型更改为unsigned int,因为如果您正在摆弄这些位,您确实需要一个简单表示的数字,没有符号位或任何类似的时髦东西。理想情况下,您应该在顶部的 typedef 中包含<cstdint>标头和 using或某些内容。::std::uint32_t