One way of doing this would be using x-macros. Though not as pretty compared to reflection that is built into a language. Using macro does make the code a little harder to read, but it is pretty straight forward.
#include <stdio.h>
#include <stdint.h>
#define HDR_STRUCT_FIELDS \
FLD(0, Field_1, uint32_t, 3) \
FLD(1, Field_2, uint16_t, 4) \
FLD(2, Field_3, uint8_t, 5)
#define FLD(idx, fld, dt, initVal) dt fld;
typedef struct
{
HDR_STRUCT_FIELDS
} HdrData_t;
#undef FLD
#define FLD(idx, fld, dt, initVal) .fld = initVal,
HdrData_t HeaderData =
{
HDR_STRUCT_FIELDS
};
#undef FLD
#define QUOTE(field) #field
#define FLD(idx, fld, dt, initVal) [idx] = QUOTE(fld),
const char* HeaderDataName[] =
{
HDR_STRUCT_FIELDS
};
#undef FLD
int main()
{
#define FLD(idx, fld, dt, initVal) printf("%s = %d\n", HeaderDataName[idx], HeaderData.fld);
HDR_STRUCT_FIELDS
#undef FLD
return (0);
}
Another method where the ordering of the field is not as important would be the following which uses a structure and initializing the structure.
#include <stdio.h>
#include <stdint.h>
#define HDR_STRUCT_FIELDS \
FLD(Field_1, uint32_t, 3) \
FLD(Field_2, uint16_t, 4) \
FLD(Field_3, uint8_t, 5)
#define FLD(fld, dt, initVal) dt fld;
typedef struct
{
HDR_STRUCT_FIELDS
} HdrData_t;
#undef FLD
#define FLD(fld, dt, initVal) .fld = initVal,
HdrData_t HeaderData =
{
HDR_STRUCT_FIELDS
};
#undef FLD
#define FLD(fld, dt, initVal) const char *fld;
typedef struct
{
HDR_STRUCT_FIELDS
} HdrDataFldString_t;
#undef FLD
#define STRINGIZE(field) #field
#define FLD(fld, dt, initVal) .fld = STRINGIZE(fld),
HdrDataFldString_t HdrDataFldString =
{
HDR_STRUCT_FIELDS
};
#undef FLD
int main()
{
#define FLD(fld, dt, initVal) printf("%s = %d\n", HdrDataFldString.fld, HeaderData.fld);
HDR_STRUCT_FIELDS
#undef FLD
return (0);
}