Standard C does not support either. However, something quite similar can be implemented via macros.
I think this way of implementing default values for function arguments in C is one of the coolest ways in my honest opinion. I implemented it without using the compound struct literal hack so that the compiler utilizes registers like rdi,rsi,rdx,rcx for the arguments in amd64; I prefer the small number of CPU cycles saved to the nice benefits coming from the compound struct literal hack: named arguments, freely ordered arguments and the ability to omit any arguments for value 0:
/**
* \brief Verbatim! You can use it to pass more than one argument packed as
* one single argument into a macro function.
*/
#define V(...) __VA_ARGS__
#define __PICK_64TH( \
_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,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63, N, ...) N
#define __SEQ_FROM_63_TO_0() \
63, 62, 61, 60, \
59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \
49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
39, 38, 37, 36, 35, 34, 33, 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 __ARG_CNT_IMPL(...) __PICK_64TH(__VA_ARGS__)
#define __SEQ_FOR_COMMA_DETECTION() \
1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 0, 0
#define __HASCOMMA(...) \
__ARG_CNT_IMPL(__VA_ARGS__, __SEQ_FOR_COMMA_DETECTION())
#define __COMMA(...) ,
#define __NARG_HELPER1(a, b, N) __NARG_HELPER2(a, b, N)
#define __NARG_HELPER2(a, b, N) __NARG_HELPER3_ ## a ## b(N)
#define __NARG_HELPER3_01(N) 1
#define __NARG_HELPER3_00(N) 0
#define __NARG_HELPER3_11(N) N
#define __NARG_IMPL(...) \
__NARG_HELPER1( \
__HASCOMMA(__VA_ARGS__), \
__HASCOMMA(__COMMA __VA_ARGS__), \
__ARG_CNT_IMPL(__VA_ARGS__, __SEQ_FROM_63_TO_0()))
#define __start_glueing(a, b) __glue_impl(a, b)
#define __glue_impl(a, b) a ## b
#define __VA_ARGCNT_WITH_UNDERSCORE(...) \
__start_glueing(_, __NARG_IMPL(__VA_ARGS__))
#define __vafunc_impl(func_name, ...) \
__start_glueing(func_name, __VA_ARGCNT_WITH_UNDERSCORE(__VA_ARGS__))
/**
* \details Usage Example:
* #define foo(...) _vafunc(foo, __VA_ARGS__)
* foo(0, 0) // gets converted to foo2(0, 0)
*/
#define _vafunc(func_name, ...) \
__vafunc_impl(func_name, __VA_ARGS__) (__VA_ARGS__)
#define __REPLACE_0_WITH_DEF_VAL_1(def1, arg1) \
(arg1) ? (arg1) : (def1)
#define __REPLACE_0_WITH_DEF_VAL_2(def1, def2, arg1, arg2) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2)
#define __REPLACE_0_WITH_DEF_VAL_3(def1, def2, def3, arg1, arg2, arg3) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2), \
(arg3) ? (arg3) : (def3)
#define __REPLACE_0_WITH_DEF_VAL_4(def1, def2, def3, def4, arg1, arg2, arg3, arg4) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2), \
(arg3) ? (arg3) : (def3), \
(arg4) ? (arg4) : (def4)
#define __REPLACE_0_WITH_DEF_VAL_5(def1, def2, def3, def4, def5, arg1, arg2, arg3, arg4, arg5) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2), \
(arg3) ? (arg3) : (def3), \
(arg4) ? (arg4) : (def4), \
(arg5) ? (arg5) : (def5)
#define __REPLACE_0_WITH_DEF_VAL_6(def1, def2, def3, def4, def5, def6, arg1, arg2, arg3, arg4, arg5, arg6) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2), \
(arg3) ? (arg3) : (def3), \
(arg4) ? (arg4) : (def4), \
(arg5) ? (arg5) : (def5), \
(arg6) ? (arg6) : (def6)
#define __REPLACE_0_WITH_DEF_VAL_7(def1, def2, def3, def4, def5, def6, def7, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2), \
(arg3) ? (arg3) : (def3), \
(arg4) ? (arg4) : (def4), \
(arg5) ? (arg5) : (def5), \
(arg6) ? (arg6) : (def6), \
(arg7) ? (arg7) : (def7)
#define __REPLACE_0_WITH_DEF_VAL_8(def1, def2, def3, def4, def5, def6, def7, def8, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2), \
(arg3) ? (arg3) : (def3), \
(arg4) ? (arg4) : (def4), \
(arg5) ? (arg5) : (def5), \
(arg6) ? (arg6) : (def6), \
(arg7) ? (arg7) : (def7), \
(arg8) ? (arg8) : (def8)
// Exuse me for the wall of text here!
#define __REPLACE_0_WITH_DEF_VAL_9(def1, def2, def3, def4, def5, def6, def7, def8, def9, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2), \
(arg3) ? (arg3) : (def3), \
(arg4) ? (arg4) : (def4), \
(arg5) ? (arg5) : (def5), \
(arg6) ? (arg6) : (def6), \
(arg7) ? (arg7) : (def7), \
(arg8) ? (arg8) : (def8), \
(arg9) ? (arg9) : (def9)
#define __REPLACE_0_WITH_DEF_VAL_10(def1, def2, def3, def4, def5, def6, def7, def8, def9, def10, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2), \
(arg3) ? (arg3) : (def3), \
(arg4) ? (arg4) : (def4), \
(arg5) ? (arg5) : (def5), \
(arg6) ? (arg6) : (def6), \
(arg7) ? (arg7) : (def7), \
(arg8) ? (arg8) : (def8), \
(arg9) ? (arg9) : (def9), \
(arg10) ? (arg10) : (def10)
#define __REPLACE_0_WITH_DEF_VAL_11(def1, def2, def3, def4, def5, def6, def7, def8, def9, def10, def11, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2), \
(arg3) ? (arg3) : (def3), \
(arg4) ? (arg4) : (def4), \
(arg5) ? (arg5) : (def5), \
(arg6) ? (arg6) : (def6), \
(arg7) ? (arg7) : (def7), \
(arg8) ? (arg8) : (def8), \
(arg9) ? (arg9) : (def9), \
(arg10) ? (arg10) : (def10), \
(arg11) ? (arg11) : (def11)
#define __REPLACE_0_WITH_DEF_VAL_12(def1, def2, def3, def4, def5, def6, def7, def8, def9, def10, def11, def12, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2), \
(arg3) ? (arg3) : (def3), \
(arg4) ? (arg4) : (def4), \
(arg5) ? (arg5) : (def5), \
(arg6) ? (arg6) : (def6), \
(arg7) ? (arg7) : (def7), \
(arg8) ? (arg8) : (def8), \
(arg9) ? (arg9) : (def9), \
(arg10) ? (arg10) : (def10), \
(arg11) ? (arg11) : (def11), \
(arg12) ? (arg12) : (def12)
#define __REPLACE_0_WITH_DEF_VAL_13(def1, def2, def3, def4, def5, def6, def7, def8, def9, def10, def11, def12, def13, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2), \
(arg3) ? (arg3) : (def3), \
(arg4) ? (arg4) : (def4), \
(arg5) ? (arg5) : (def5), \
(arg6) ? (arg6) : (def6), \
(arg7) ? (arg7) : (def7), \
(arg8) ? (arg8) : (def8), \
(arg9) ? (arg9) : (def9), \
(arg10) ? (arg10) : (def10), \
(arg11) ? (arg11) : (def11), \
(arg12) ? (arg12) : (def12), \
(arg13) ? (arg13) : (def13)
#define __REPLACE_0_WITH_DEF_VAL_14(def1, def2, def3, def4, def5, def6, def7, def8, def9, def10, def11, def12, def13, def14, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2), \
(arg3) ? (arg3) : (def3), \
(arg4) ? (arg4) : (def4), \
(arg5) ? (arg5) : (def5), \
(arg6) ? (arg6) : (def6), \
(arg7) ? (arg7) : (def7), \
(arg8) ? (arg8) : (def8), \
(arg9) ? (arg9) : (def9), \
(arg10) ? (arg10) : (def10), \
(arg11) ? (arg11) : (def11), \
(arg12) ? (arg12) : (def12), \
(arg13) ? (arg13) : (def13), \
(arg14) ? (arg14) : (def14)
#define __REPLACE_0_WITH_DEF_VAL_15(def1, def2, def3, def4, def5, def6, def7, def8, def9, def10, def11, def12, def13, def14, def15, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2), \
(arg3) ? (arg3) : (def3), \
(arg4) ? (arg4) : (def4), \
(arg5) ? (arg5) : (def5), \
(arg6) ? (arg6) : (def6), \
(arg7) ? (arg7) : (def7), \
(arg8) ? (arg8) : (def8), \
(arg9) ? (arg9) : (def9), \
(arg10) ? (arg10) : (def10), \
(arg11) ? (arg11) : (def11), \
(arg12) ? (arg12) : (def12), \
(arg13) ? (arg13) : (def13), \
(arg14) ? (arg14) : (def14), \
(arg15) ? (arg15) : (def15)
#define __REPLACE_0_WITH_DEF_VAL_16(def1, def2, def3, def4, def5, def6, def7, def8, def9, def10, def11, def12, def13, def14, def15, def16, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16) \
(arg1) ? (arg1) : (def1), \
(arg2) ? (arg2) : (def2), \
(arg3) ? (arg3) : (def3), \
(arg4) ? (arg4) : (def4), \
(arg5) ? (arg5) : (def5), \
(arg6) ? (arg6) : (def6), \
(arg7) ? (arg7) : (def7), \
(arg8) ? (arg8) : (def8), \
(arg9) ? (arg9) : (def9), \
(arg10) ? (arg10) : (def10), \
(arg11) ? (arg11) : (def11), \
(arg12) ? (arg12) : (def12), \
(arg13) ? (arg13) : (def13), \
(arg14) ? (arg14) : (def14), \
(arg15) ? (arg15) : (def15), \
(arg16) ? (arg16) : (def16)
#define __ARGS_FOR_CALL_FUNC_WITH_DEF_VAL_IMPL(...) \
__start_glueing( __REPLACE_0_WITH_DEF_VAL_, __NARG_IMPL(__VA_ARGS__) )
#define __ARGS_FOR_CALL_FUNC_WITH_DEF_VAL(defvals, ...) \
__ARGS_FOR_CALL_FUNC_WITH_DEF_VAL_IMPL(V(defvals)) (defvals, __VA_ARGS__)
/**
* \brief Call a function with default values, a default value replaces a 0.
* \details
* Usage Example:
* int add_(int a, int b) {
* return a + b;
* }
* #define add(...) _cwdv(add_, V(0, 100), __VA_ARGS__)
* fprintf(stdout, "%d\n", add(8,0)); // 108
*/
#define _cwdv(func_name, defvals, ...) \
func_name( \
__ARGS_FOR_CALL_FUNC_WITH_DEF_VAL(V(defvals), __VA_ARGS__) \
)
Please take a look at the comments for usage example :) _cwdv is the macro for default values on function arguments.
You can also combine it with the macro called _vafunc in the code above if you'd like the user to be able to omit writing 0 for a specific argument or two:
int add_2_(int a, int b) { return a+b; } // Or return a+b+0+100
int add_3_(int a, int b, int c) { return a+b+c+100; }
int add_4_(int a, int b, int c, int d) { return a+b+c+d; }
#define add_2(...) _cwdv(add_2_, V(0, 100), __VA_ARGS__)
#define add_3(...) _cwdv(add_3_, V(0, 100, 0), __VA_ARGS__)
#define add_4(...) _cwdv(add_4_, V(0, 100, 0, 100), __VA_ARGS__)
#define add(...) _vafunc(add, __VA_ARGS__)
Here's how you can have function overloading in C via C11 _Generic:
const char* foo_property_2(foo_t* foo, int bar);
const char* foo_property_3i(foo_t* foo, const char* foobar, int bar);
const char* foo_property_3c(foo_t* foo, const char* foobar, char bar);
#define foo_property_3(a1, a2, a3) _Generic((a3), \
char : foo_property_3c, \
unsigned char: foo_property_3c, \
int : foo_property_3i \
)(a1, a2, a3)
#define foo_property(...) _vafunc(foo_property, __VA_ARGS__)
Combine default values for function parameters and function overloading:
int add_2_(int a, int b) { return a+b; } // Or return a+b+0+100
#define add_2(...) _cwdv(add_2_, V(0, 100), __VA_ARGS__)
int add_3_c(int a, int b, char c) { return a+b+c+100; }
#define add_3_c__(...) _cwdv(add_3_c, V(0, 100, 0), __VA_ARGS__)
int add_3_i(int a, int b, int c) { return a+b+c+500; }
#define add_3_i__(...) _cwdv(add_3_i, V(0, 100, 0), __VA_ARGS__)
__attribute__((always_inline)) inline int add_3_c_(int a, int b, char c) { return add_3_c__(a, b, c); }
__attribute__((always_inline)) inline int add_3_i_(int a, int b, int c) { return add_3_i__(a, b, c); }
#define add_3(a1, a2, a3) _Generic((a3), \
unsigned char : add_3_c_, \
char : add_3_c_, \
int : add_3_i_ \
)(a1, a2, a3)
int add_4_(int a, int b, int c, int d) { return a+b+c+d; }
#define add_4(...) _cwdv(add_4_, V(0, 100, 0, 100), __VA_ARGS__)
#define add(...) _vafunc(add, __VA_ARGS__)
int main(int argc, char * argv[]) {
fprintf(stdout, "%d\n", add(8, 0)); // 108
fprintf(stdout, "%d\n", add(8, 0, 0)); // 608
fprintf(stdout, "%d\n", add(8, 0, (char)10)); // 218
fprintf(stdout, "%d\n", add(8, 0, 0, 0)); // 208
return 0;
}