//C has no optional parameters and no overloading:
//the options travel in a struct, and zero in a field means "by default"
typedef struct {
const char *message; //nullptr: "Goodbye!"
int times; //0: once
} GoodbyeOptions;
void sayGoodbyeWith(GoodbyeOptions options) {
const char *message =
options.message != nullptr ? options.message : "Goodbye!";
int times = options.times > 0 ? options.times : 1;
for (int i = 0; i < times; i++) {
printf("%s\n", message);
}
}
//the macro builds the struct from named fields: a field not named is zero;
//defaults are not written into the macro, otherwise the caller
//who sets that field again would get the warning -Woverride-init
#define sayGoodbye(...) sayGoodbyeWith((GoodbyeOptions){__VA_ARGS__})
sayGoodbye();
//prints "Goodbye!"
sayGoodbye(.message = "see you");
//prints "see you"
sayGoodbye(.times = 2, .message = "bye");
//prints "bye" twice