简体   繁体   中英

Adding elements inside a typedef while taking care of the overall size of the struct?

I have a typedef 'ed struct which currently looks like this:

typedef struct Sys_Inject
{
   uint16_t num;
   uint16_t alternative;
   uint8_t  delay;
   uint8_t  thresh;
   uint8_t  reserved[2];
   BOOL32   state;
   options_select_t sel;
   uint32_t per;
} Sys_Inject_t;

I want to get rid of the elements BOOL32 state; and options_select_t sel; and define them inside the uint8_t reserved[2] array such that reserved[0] = state and reserved[1] = sel . BOOL32 is defined in another module as:

typedef BOOL32 (*FScallback_t)(uint32_t);

Also options_select_t is an enum and is defined as:

typedef enum options_select_e
{
    TEST_DEFAULT = 0,
    TEST_CURRENT,
    TEST_SAVED,
}options_select_t;

What is the actual size of BOOL32 in this case? Is it 32 bits? Also, is the size of the enum 8 bits for each element?

Note that reserved is an array with two elements, so it is 16 bits in total. How do I fit the two elements state and sel in it?

The most reliable way is to just use the compiler's information:

typedef struct Sys_Inject {
    uint16_t num;
    uint16_t alternative;
    uint8_t delay;
    uint8_t thresh;
    uint8_t reserved[2 + sizeof(BOOL32) + sizeof(options_select_t)];
    uint32_t per;
} Sys_Inject_t;

Here's a program that statically checks that:

  • the struct maintains the same size
  • the offset of the per member in the struct is the same after

Live On Coliru

#include <cstdint>
#include <cstddef>

enum BOOL32 : uint32_t { FALSE, TRUE };

enum options_select_t {
    TEST_DEFAULT = 0,
    TEST_CURRENT,
    TEST_SAVED,
};

struct OLD_Sys_Inject {
    uint16_t num;
    uint16_t alternative;
    uint8_t delay;
    uint8_t thresh;
    uint8_t reserved[2];
    BOOL32 state;
    options_select_t sel;
    uint32_t per;
};

typedef struct Sys_Inject {
    uint16_t num;
    uint16_t alternative;
    uint8_t delay;
    uint8_t thresh;
    uint8_t reserved[2 + sizeof(BOOL32) + sizeof(options_select_t)];
    uint32_t per;
} Sys_Inject_t;

static_assert(sizeof(OLD_Sys_Inject) == sizeof(Sys_Inject));
static_assert(offsetof(OLD_Sys_Inject, per) == offsetof(Sys_Inject, per));

int main() {}

BOOL32 is most likely 32 bits, given its name. But you did not show the declaration for BOOL32 , you actually showed the declaration of FScallback_t , which is a pointer to a function that returns a BOOL32 .

The size of options_select_t is compiler defined . It may be 1 byte, or it may be 2 bytes, or it may be 4 bytes, etc. There is no way to answer that without knowing what compiler you are using, and what options you are specifying when compiling the code with it.

But, in any case, reserved is only 2 bytes in size. There is no way to fit state into reserved[0] if BOOL32 is more than 8 bits, or to fit sel into reserved[1] if options_select_t is more than 8 bits. Nor should you try. Assuming you need to preserve the same size of the original Sys_Inject_t , you will need to extend the size of reserved to include the sizes of BOOL32 and options_select_t , eg.

typedef struct Sys_Inject
{
   uint16_t num;
   uint16_t alternative;
   uint8_t  delay;
   uint8_t  thresh;
   uint8_t  reserved[2 + sizeof(BOOL32) + sizeof(options_select_t) + any padding that was present between the original fields];
   uint32_t per;
} Sys_Inject_t;
typedef struct Sys_Inject
{
   uint16_t num;
   uint16_t alternative;
   uint8_t  delay;
   uint8_t  thresh;
   union 
   {
        uint8_t  reserved[2];
        struct 
        {
            uint8_t state: 1;
            options_select_t sel: 2;
        };
   };
   uint32_t per;
} Sys_Inject_t;

or

typedef struct Sys_Inject
{
   uint16_t num;
   uint16_t alternative;
   uint8_t  delay;
   uint8_t  thresh;
   union 
   {
        uint8_t  reserved[2];
        struct 
        {
            uint8_t state: 1;
            uint8_t :7;
            options_select_t: 8;
        };
   };
   uint32_t per;
} Sys_Inject_t;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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