This problem can be solved without any need for preprocessor with a help of anonymous structs introduced in C11.
Define the flash type as a union that contains members embedded into anonymous struct. Make char _pad[0x10000]
the other member of the union to force the total size of the introduced type.
typedef union {
struct {
uint16_t firstElement;
uint8_t secondElementArray[32];
float thirdElement;
};
char _pad[0x10000];
} flash_t;
This solution is robust to any modifications to the layout of the struct members. Moreover, this avoids problem of defining zero-length array that is technically forbidden by C standard (though allowed in GCC). Additionally, one can add a static assert to check if the maximal size of the flash got overflown.
Example program:
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
typedef union {
struct {
uint16_t firstElement;
uint8_t secondElementArray[32];
float thirdElement;
// int kaboom[20000]; // will trigger assert if uncommented
};
char _pad[0x10000];
} flash_t;
_Static_assert(sizeof(flash_t) == 0x10000, "Oops, flash_t got too large");
int main() {
flash_t flash;
printf("offsetof(flash.firstElement) = %zi\n", offsetof(flash_t, firstElement));
printf("offsetof(flash.secondElementArray) = %zi\n", offsetof(flash_t, secondElementArray));
printf("offsetof(flash.thirdElement) = %zi\n", offsetof(flash_t, thirdElement));
printf("sizeof(flash) = %zi\n", sizeof flash);
return 0;
}
Produces expected output:
offsetof(flash.firstElement) = 0
offsetof(flash.secondElementArray) = 2
offsetof(flash.thirdElement) = 36
sizeof(flash) = 65536
EDIT
As suggested in the comment the union member _pad
could be renamed to _rawData
because semantics of _pad
differs from pad
in the question.
If a member pad
within the type is required then one could add it as a flexible member at the end of anonymous struct.
typedef union { struct { ...; uint8_t pad[]; }; char _rawData[0x10000]; } flash_t;