【问题标题】:Overlapped bit-field in CC中的重叠位域
【发布时间】:2014-10-16 15:02:45
【问题描述】:

我是一名计算机科学专业的学生。

现在,我正在用 C 语言开发一个计算机架构项目,该项目模拟处理器。

指令的种类很多

 31     27 26     22 21     17 16                              0
 ---------------------------------------------------------------
|    op   |    ra   |    rb   |             imm17               |
 ---------------------------------------------------------------

 31     27 26     22 21     17 16                7 6 5 4       0
 ---------------------------------------------------------------
|    op   |    ra   |    rb   |       imm10       | m |  shamt  |
 ---------------------------------------------------------------

 31     27 26     22 21                                        0
 ---------------------------------------------------------------
|    op   |    ra   |                  imm22                    |
 ---------------------------------------------------------------

所以,我想制作一个 C 结构,其中包含与每个元素对应的位域,例如 op、ra 等。

起初,我认为我可以使用联合和嵌套结构。

例如,我写了这样的代码:

struct instr_t {
    union {
        uint32_t imm22 : 22;

        struct {
            union {
                uint32_t imm17: 17;
                struct {
                    uint8_t shamt: 5;
                    uint8_t mode : 2;
                    uint16_t imm10 : 10;
                };
            };
            uint8_t rb : 5;
        };
    };

    uint8_t ra : 5;
    uint8_t op : 5;
}

我预计 sizeof(struct instr_t) 的结果是 4,但实际是 12。

也许嵌套结构有一些填充。

所以,这是我的问题:

如何实现重叠的 C 位域?

有没有人可以推荐一种更好的方法来在 C 中实现多种类型的指令?

谢谢!

【问题讨论】:

  • 为什么不使用单个无符号整数来保存您的位?
  • @JoeManiaci 我非常怀疑这一点。 :)
  • 我认为 2501 的意思是使用 32 位整数并使用按位运算来设置您需要的值。
  • 有一个 struct instr_t{...} 和 4 个联合条目:一个 sub-struct{...} R、一个 sub-struct{...} I、一个 sub-struct{...} J 和一个 uint32_t asInt32。尔格:struct instr_t{union{struct{/* Fields of R-type */} R; struct{/* Fields of I-type */} I; struct{/* Fields of J-type */} J; uint32_t asInt32;};};
  • 2 条建议!每个指令结构的按位运算和联合。谢谢你们。我更喜欢后一种:)

标签: c struct unions bit-fields


【解决方案1】:

位域成员必须存储在同一个存储单元中才能连续布局:

struct instr_1_t {
    uint32_t imm22 : 17;
    uint32_t rb : 5;
    uint32_t ra : 5;
    uint32_t op : 5;
};

struct instr_2_t {
    uint32_t shamt: 5;
    uint32_t m: 2;
    uint32_t imm10 : 10;
    uint32_t rb : 5;
    uint32_t ra : 5;
    uint32_t op : 5;
};

struct instr_3_t {
    uint32_t imm22 : 22;
    uint32_t ra : 5;
    uint32_t op : 5;
};

union instr_t {
    struct {
        uint32_t pad : 22;
        uint32_t op : 5;
    };
    instr_1_t instr_1;
    instr_2_t instr_2;
    instr_3_t instr_3;
};

static_assert(sizeof(instr_t) == sizeof(uint32_t), "sizeof(instr_t) != sizeof(uint32_t)");

void handle_instr(instr_t i) {
    switch(i.op) {
        //
    }
}

【讨论】:

  • 注意,如果你颠倒位域的顺序,你就不需要在instr_t中手动填充op
  • 更新答案!我喜欢它:)
【解决方案2】:

Maxim 给出了正确答案。

我还建议查看此代码以了解为什么 sizeof instr_t 给出 12 :)

typedef struct s1{
    uint8_t shamt: 5;
    uint8_t mode : 2;
    uint16_t imm10 : 10;
} s_1;

typedef union u1{
    uint32_t imm17: 17;
    s_1 member0;
} u_1;

typedef struct s2{
    u_1 member1;
    uint8_t rb : 5;
} s_2;

typedef union u2{
    uint32_t imm22 : 22;
    s_2 member3;
} u_2;

typedef struct instr_t {
    u_2 member4;
    uint8_t ra : 5;
    uint8_t op : 5;
} s_instr;

int main(int argc, char* argv[])
{
    printf("sizes s_1=%d, u_1=%d, s_2=%d, u_2=%d, s_instr=%d\n", sizeof(s_1), sizeof(u_1), sizeof(s_2), sizeof(u_2), sizeof(s_instr)); 
    printf("uint8_t=%d, uint16_t=%d, uint32_t=%d\n", sizeof(uint8_t), sizeof(uint16_t), sizeof(uint32_t));
    printf("Sizeof instr_t is %d\n", sizeof(s_instr));
}

希望这会有所帮助!

干杯!

【讨论】:

  • 谢谢!我认为这是因为字节对齐。我从来没有考虑过。
【解决方案3】:

位域不可移植。您永远不知道相同的位域定义是否会在两个不同的编译器上为您带来相同的结果。位域在多线程程序中也有有趣的语义。

使用 C++ 并使用适当的内联访问器编写一个类。我的意思是你是一名计算机科学专业的学生,​​你知道 C++,对吧?

如果出于某种疯狂的原因,您的上级要求使用 C 编写代码,请使用移位和屏蔽操作编写一个包含一个 uint32_t 成员和单独访问器函数的结构。显然也是内联的。

【讨论】:

  • 我没有听说位域不可移植。这不是标准的东西吗?不幸的是,我应该只用 C 编写代码:(。无论如何,谢谢!
  • 布局不可移植。例如,您永远不知道您的“imm17”和“shamt”字段是如何重叠的。
  • 我所知道的是后一个位域占用更多的有效位。我想,那么,我知道布局,不是吗?
  • 谢谢!我明白你说的。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-06
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 2010-12-05
  • 1970-01-01
相关资源
最近更新 更多