Optional parameter values

Functions

//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