In an embedded project, I use a library that provides a macro for initializing a structure. This provides reasonable defaults, but the defaults depend on other parameters. I want to override one or more values of this designated initializer, because initializing the values afterwards generates overhead.
Ideally, I don't want to copy-paste all of the macro's, because I then have to manage third-party code. If the library changes it's defaults, I don't want to do that too.
Is there a way of combining or overriding designated initializers, so there is no overhead? The code has to be C99 compliant and portable.
Some example code to demonstrate the issue:
#if SITUATION
#define LIBRARY_DEFAULTS \
{ \
.field_a = 1, \
.field_b = 2, \
.field_c = 3 \
}
#else
#define LIBRARY_DEFAULTS \
{ \
.field_a = 100, \
.field_b = 200, \
.field_c = 300, \
.field_d = 400, \
.field_e = 500 \
}
#endif
/* The following is what I want (or similar), but (of course) doesn't
work. */
// #define MY_DEFAULTS = LIBRARY_DEFAULTS + { .field_a = 100 }
int main(void) {
/* The exact definition of something also depends on situation. */
struct something library_thing = LIBRARY_DEFAULTS;
/* This generates overhead, and I want to avoid this. It is certain
that the field exists. */
library_thing.field_a = 100;
}
You could wrap your library_thing
in an outer structure, and do your overrides from the outer structure's initializer:
#include <stdio.h>
struct foo {
int a,b,c;
};
#define FOO_DEFAULTS { .a = 1, .b = 2, .c = 3 }
int main() {
struct {
struct foo x;
} baz = {
.x = FOO_DEFAULTS,
.x.a = 4,
};
printf("%d\n", baz.x.a); // prints 4
}
In fact, you can even do
.x = FOO_DEFAULTS,
.x = {.a = 4},
if you need to really "merge" two initializers.
This compiles fine on Clang (7.0.2) but generates a warning under -Winitializer-overrides
. Checking the generated code confirms that the structure is initialized with 4, 2, 3
so there is no additional overhead from this trick.