Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Actual sizeof padded struct, (sum of member sizes, without padding for alignment)

sizeof() returns size of structure including padding of members for alignment. Which is fine. Don't need to pack the structure to have 0 padding.

Just need to get get(or calculate) sum of sizes of members of structure to compare (using it in static compile time assert).

When you have members small in size, they absence/difference is not get caught. Members are mainly char arrays

Is it possible to get that number at compile time (or at run time)?

Or how else can I make sure the 'effective' size is what I expect and avoid accidental change from braking the program?

Original intention is to avoid bugs if A or B modified to be different by mistake. Using STATIC_ASSERT( sizeof(A) == sizeof(B) ) which doesn't work for some 'small' differences due to padding.

note: A and B should be similar, but in given design it's not possible to reuse A in both parts of the program. This check is to make sure if someone changes only A or only B, it can not compiled.

like image 368
sny Avatar asked Nov 01 '22 07:11

sny


1 Answers

You can #include the same header twice. Once with packed enabled and once without. And obviously the macro would also change the name of the packed struct to something different to the real struct name.

Here's an example. The header file, say test.h, is shown below. It shows two struct which have different unpacked sizes but same packed sizes.

#ifdef ENABLE_PACKED
#define PACKED(x) __attribute__ ((__packed__)) x##_packed
#else
#define PACKED(x) x
#endif

struct PACKED(my_struct1) {
    char c1;
    int i1;
    char c2;
    int i2;
};

struct PACKED(my_struct2) {
    char c1;
    char c2;
    int i1;
    int i2;
};

#ifdef ENABLE_PACKED
_Static_assert(sizeof(struct my_struct1_packed) ==
               sizeof(struct my_struct2_packed), "Error");
#endif

#undef PACKED

Note that you really only need to define ENABLE_PACKED and #include test.h in one file for the static assert to be tested. So you can even just create a dummy.c file which includes test.h twice and have your build compile dummy.c every time but not actually use it in any real release object. That way, all your real .c files do not even need to know about this at all and can just include all header files normally.

like image 127
kaylum Avatar answered Nov 11 '22 06:11

kaylum