简体   繁体   English

C中重叠的位字段

[英]Overlapped bit-field in C

I'm a computer science student. 我是一名计算机科学专业的学生。

Now, I'm working on a computer architecture project in C, which simulates a processor. 现在,我正在研究用C模拟处理器的计算机体系结构项目。

There are many types of instructions such as 有许多类型的指令,如

 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                    |
 ---------------------------------------------------------------

So, I wanted to make a C structure which contains bit-fields corresponding to each elements such as op, ra and so on. 所以,我想制作一个C结构,其中包含与每个元素相对应的位字段,如op,ra等。

At first, I thought that I could use unions and nested structs. 起初,我认为我可以使用联合和嵌套结构。

For example, I wrote code like: 例如,我编写的代码如下:

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;
}

I expected that the result of sizeof(struct instr_t) would be 4 but the reality was 12. 我期望sizeof(struct instr_t)的结果是4,但现实是12。

Maybe the nested structs got some paddings. 也许嵌套的结构有一些填充。

So, here is my qeustion: 所以,这是我的qeustion:

How can one achieve overlapped C bit-fields? 如何实现重叠的C比特字段?

or 要么

Does anybody can recommend a better way to implement multiple types of instruction in C? 有人能推荐一种更好的方法在C中实现多种类型的指令吗?

Thank you! 谢谢!

The bit-fields members must be stored in the same storage unit to be layed out contiguously: 位字段成员必须存储在相同的存储单元中才能连续布局:

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) {
        //
    }
}

Maxim gave the correct answer. 马克西姆给出了正确答案。

I also suggest looking over this code to understand why sizeof instr_t was giving 12 :) 我也建议查看这段代码,以了解为什么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));
}

Hope this helps! 希望这可以帮助!

Cheers! 干杯!

Bitfields are not portable. 位域不可移植。 You never know if the same bitfield definition gets you the same results on two different compilers. 你永远不知道相同的位域定义是否在两个不同的编译器上获得相同的结果。 Bitfields also have let's say interesting semantics in multi-threaded programs. Bitfields也让我们说多线程程序中有趣的语义。

Go with C++ and write a class with appropriated inlined accessors. 使用C ++编写一个带有适当内联访问器的类。 I mean you are a computer science student, you know C++, right? 我的意思是你是一名计算机科学专业的学生,​​你知道C ++,对吗?

If for some mad reason your superiors demand that the code is written in C, write a struct with one uint32_t member and individual accessor functions using shift and masking operations. 如果由于某些疯狂的原因,您的上级要求代码是用C语言编写的,请使用移位和屏蔽操作编写一个带有一个uint32_t成员和各个访问器函数的结构。 Obviously also inlined. 显然也有内联。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM