From https://stackoverflow.com/a/78487689/2706707
Requires C99, of course. Credits in the code. (I would not likely have figured this out on my own.)
c-default-args.h
#ifndef DUTHOMHAS_C_DEFAULT_ARGUMENTS_H
#define DUTHOMHAS_C_DEFAULT_ARGUMENTS_H
#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
#error "Variadic Macros require C99 or better"
#endif
// Copyright 2021 Michael Thomas Greer
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt )
// This is a VERY simple library to provide default argument capabilities to C functions.
// I suppose it is possible to dive very much deeper down the preprocessor rabbit hole
// and make using this really short and pretty, but the cost is enormous and this suffices
// me. Example usage:
//
// #include <duthomhas/c-default-args.h>
//
// int my_function( int a, int b, int c );
// #define my_function(...) DUTHOMHAS_CALL_OVERLOAD(my_function_,__VA_ARGS__)
// #define my_function_0() my_function( -7, 512, 42 )
// #define my_function_1(a) my_function( a, 512, 42 )
// #define my_function_2(a,b) my_function( a, b, 42 )
// #define my_function_3(a,b,c) my_function( a, b, c )
//
// int x = my_function(); // same as: int x = my_function( -7, 512, 42 );
// int y = my_function( 15, 4000 ); // same as: int y = my_function( 15, 4000, 42 );
//
// The equivalent construct in C++ would be:
//
// int my_function( int a=-7, int b=512, int c=42 );
//
// Do not define my_function_N for the argument lists that are not permitted and let the
// compiler complain for you if the user did not provide a correct number of arguments.
//
// #define my_function(...) DUTHOMHAS_CALL_OVERLOAD(my_function_,__VA_ARGS__)
// #define my_function_1(a) my_function( a, M_PI, 74 )
// #define my_function_3(a,b,c) my_function( a, b, c )
//
// int x = my_function(); // compile error
// int y = my_function( 3 ); // OK
// int y = my_function( 3, 5 ); // compile error
// int z = my_function( 3, 5, 7 ); // OK
//
// Not only too few arguments, but too many arguments will lead to compiler error as well.
//
// int q = my_function( 1, 2, 3, 4, 5 ); // compiler error
//
// The compile error will look something like:
//
// "implicit declaration of function 'my_function_0' is invalid"
// "unresolved external symbol my_function_0 referenced in function main"
#ifdef __clang__
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#endif
// Francesco Pretto (ceztko) --> https://stackoverflow.com/a/26685339/2706707
#ifdef _MSC_VER // Microsoft compilers
#define DUTHOMHAS_EXPAND(x) x
#define DUTHOMHAS_NARGS_0(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32, VAL, ...) VAL
#define DUTHOMHAS_NARGS_1(...) DUTHOMHAS_EXPAND(DUTHOMHAS_NARGS_0(__VA_ARGS__,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))
#define DUTHOMHAS_AUGMENTER(...) unused, __VA_ARGS__
#define DUTHOMHAS_NARGS(...) DUTHOMHAS_NARGS_1(DUTHOMHAS_AUGMENTER(__VA_ARGS__))
#else // Others
#define DUTHOMHAS_NARGS(...) DUTHOMHAS_NARGS_0(0, ## __VA_ARGS__, 32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
#define DUTHOMHAS_NARGS_0(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,N,...) N
#endif
// Braden Steffaniak --> https://stackoverflow.com/a/24028231/2706707
#define DUTHOMHAS_GLUE(x, y) x y
#define DUTHOMHAS_OVERLOAD_MACRO2(name, count) name##count
#define DUTHOMHAS_OVERLOAD_MACRO1(name, count) DUTHOMHAS_OVERLOAD_MACRO2(name, count)
#define DUTHOMHAS_OVERLOAD_MACRO(name, count) DUTHOMHAS_OVERLOAD_MACRO1(name, count)
#define DUTHOMHAS_CALL_OVERLOAD(name, ...) DUTHOMHAS_GLUE(DUTHOMHAS_OVERLOAD_MACRO(name, DUTHOMHAS_NARGS(__VA_ARGS__)), (__VA_ARGS__))
#endif