I'm a computer science student.
Now, I'm working on a computer architecture project in C, which simulates a processor.
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.
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.
Maybe the nested structs got some paddings.
So, here is my qeustion:
or
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) {
        //
    }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With