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:
per
member in the struct is the same after#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.