Search code examples
cgccbit-fields

how to pack the size of struct contains bitfield struct in it?


Hi I'm defining the following structure in C

struct __attribute__((__packed__)) Input {
    enum {
        I_PE_left     = 0, 
        I_PE_up       = 1, 
        I_PE_right    = 2, 
        I_PE_down     = 3,
        I_LSU_left    = 4,
        I_LSU_up      = 5,
        I_LSU_right   = 6,
        I_LSU_down    = 7,
        I_LR_0        = 8,
        I_LR_1        = 9,
        I_LR_2        = 10,
        I_IMMI_0      = 11,
        I_IMMI_1      = 12,
        I_IMMI_2      = 13,
        I_UNUSE       = 15
    } src:4;
};  
struct __attribute__((__packed__)) Instr {
    struct Input inputx;
    struct Input inputy;
    struct Input inputz;
    struct Input inputzz;
};

In the above example, the sizeof(struct Instr) is 4, which means even a packed struct will take at least 1 byte.

However, I would like to push the sizeof(struct Instr) into 2 but don not know how to do it..


The full definition is as follow. I may need to recursively define structure since I would like to use the structure definition multiple times.

struct __attribute__((__packed__)) Output {
    enum {
        O_S_PE_left     = 0, 
        O_S_PE_up       = 1, 
        O_S_PE_right    = 2, 
        O_S_PE_down     = 3,
        O_S_LSU_left    = 4,
        O_S_LSU_up      = 5,
        O_S_LSU_right   = 6,
        O_S_LSU_down    = 7,
        O_S_CALC_res    = 8,
        O_S_LR_0        = 9,
        O_S_LR_1        = 10,
        O_S_LR_2        = 11,
        O_S_IMMI_0      = 12,
        O_S_IMMI_1      = 13,
        O_S_IMMI_2      = 14,
        O_S_UNUSE       = 15
    } src:4;
    enum {
        O_I_LR_0        = 0,
        O_I_LR_1        = 1,
        O_I_LR_2        = 2,
        O_I_GR          = 3,
        O_I_FIFO        = 4,
        O_I_PE_DIR      = 5,
        O_I_LSU         = 6
    } dst:3;
};
struct __attribute__((__packed__)) Input {
    enum {
        I_PE_left     = 0, 
        I_PE_up       = 1, 
        I_PE_right    = 2, 
        I_PE_down     = 3,
        I_LSU_left    = 4,
        I_LSU_up      = 5,
        I_LSU_right   = 6,
        I_LSU_down    = 7,
        I_LR_0        = 8,
        I_LR_1        = 9,
        I_LR_2        = 10,
        I_IMMI_0      = 11,
        I_IMMI_1      = 12,
        I_IMMI_2      = 13,
        I_UNUSE       = 15
    } src:4;
};  
struct __attribute__((__packed__)) Instr {
    unsigned char un_use:6;
    unsigned char ctl_id:2;
    unsigned char output_ctl_right:2;
    unsigned char output_ctl_down:2;
    unsigned char output_ctl_left:2;
    unsigned char output_ctl_up:2;
    struct Output output_right; 
    struct Output output_down; 
    struct Output output_left; 
    struct Output output_up;
    struct Input inputx;
    struct Input inputy;
    struct Input inputz;
};

Solution

  • You don't need to embed the enum in a separate struct. Just use it directly, with the enums themselves as bitfields:

    enum Input {
        I_PE_left     = 0, 
        I_PE_up       = 1, 
        I_PE_right    = 2, 
        I_PE_down     = 3,
        I_LSU_left    = 4,
        I_LSU_up      = 5,
        I_LSU_right   = 6,
        I_LSU_down    = 7,
        I_LR_0        = 8,
        I_LR_1        = 9,
        I_LR_2        = 10,
        I_IMMI_0      = 11,
        I_IMMI_1      = 12,
        I_IMMI_2      = 13,
        I_UNUSE       = 15
    };
    
    struct Instr {
        enum Input inputx:4;
        enum Input inputy:4;
        enum Input inputz:4;
        enum Input inputzz:4;
    };
    

    And compile with -fshort-enums which will make the enum type take up only 1 byte. This will give you a 2 byte struct without having to pack it.