34

Converting a C++ lib to ANSI C and it seems like though ANSI C doesn't support default values for function variables or am I mistaken? What I want is something like

int funcName(int foo, bar* = NULL);

Also, is function overloading possible in ANSI C?

Would need

const char* foo_property(foo_t* /* this */, int /* property_number*/);
const char* foo_property(foo_t* /* this */, const char* /* key */, int /* iter */);

Could of course just name them differently but being used to C++ I kinda used to function overloading.

asked Jun 7, 2010 at 8:36
1
  • 3
    No, it doesn't support any of that. Commented Jun 7, 2010 at 8:38

10 Answers 10

42

No, Standard C does not support either. Why do you feel you need to convert your C++ code to C? That could get quite tricky - I'd have thought writing wrappers would be the way to go, if your C++ must be callable from C.

answered Jun 7, 2010 at 8:37
Sign up to request clarification or add additional context in comments.

4 Comments

I'm now working in a C environment and the use of C++ code has been banned ;)... So instead of making the existing C compliant with the g++ compiler and thus being able to use C++ classes alongside the C code I'm forced to convert existing useful classes I have to C.
@ inquam: Don't. Use the language at hand, don't try to force some other language down the throat of the compiler. While it is comparatively easy to make C code work in a C++ environment, the opposite is anything but trivial (as you just came to realize). Rather re-implement your "useful classes" as a C function library than trying to "port" it 1:1.
@inquam In general, I agree with DevSolar. Particularly if you have used any C++ features such as Standard Library containers, exceptions and particularly RAII. However, if your original code simply ised C++ as "a better C", then I guess it is just about doable, though I wouldn't want to be the one doing it.
This specific library was written using c-style strings and arrays so no STL was involved. So making it work (which I now have) was basicly about removing the class structure and making functions passing the initially created object to each one. One "new" function to create the object and then use that as one of the arguments for all the other functions.
38

Nevertheless I found a "trick" to do so if you use GCC (edit December 2020) or any compiler compatible with C++2a -yes it works with 'plain C' since it is a pre-compiler trick-.

GCC has a handy ## extension on variadic macro that allows you to simulate a default argument.

The trick has limitations: it works only for 1 default value, and the argument must be the last of you function parameters.

Here is a working example.

#include <stdio.h>
#define SUM(a,...) sum( a, (5, ##__VA_ARGS__) )
int sum (a, b)
 int a;
 int b;
{
 return a + b;
}
main()
{
 printf("%d\n", SUM( 3, 7 ) );
 printf("%d\n", SUM( 3 ) );
}

In this case, I define SUM as a call to sum with the default second argument being 5.

If you call with 2 arguments (first call in main), it would be prepocessed as: sum( 3, (5, 7) );

This means:

  • 1st argument is 3
  • second argument is the result of the sequence (5, 7)... which is obviously 7!

As gcc is clever, this has no effect on runtime as the first member of the sequence is a constant and it is not needed, it will simply be discarded at compile time.

If you call with only one argument, the gcc extension will remove the VA_ARGS AND the leading coma. So it is preprocessed as:

sum( 3, (5 ) );

Thus the program gives the expected output:

10
8

So, this does perfectly simulate (with the usual macro limitations) a function with 2 arguments, the last one being optional with a default value applied if not provided.

Edit

-a) It does also work with CLANG (and possibly other compilers)

-b) A version that does NOT complain about unused arguments:

#define DEF_OR_ARG(z,a,arg,...) arg
#define SUM(a,...) sum( a, DEF_OR_ARG(,##__VA_ARGS__,__VA_ARGS__,5))

[Edit - October 2020] : You could also try the new __VA_OPT__ that was standardised with c++2a (and should work in plain C too) instead of ## which is a gcc extension. Typical usage is __VA_OPT__(,) that would add the coma when the argument list is non-empty and otherwise outputs nothing.

[Edit - December 2020] : So the above trick, with __VA_OPT__, becomes:

#define DEF_OR_ARG(value,...) value
#define SUM(a,...) sum( a, DEF_OR_ARG(__VA_ARGS__ __VA_OPT__(,) 5))

Unlike the 'sequence trick' that might complain for unused variables, this only involves the pre-compiler and is more readable.

When SUM is called with only one argument, ... is empty and __VA_OPT__ does not output anything, thus DEF_OR_ARG(__VA_ARGS__ __VA_OPT(,) 5) becomes DEF_OR_ARG( 5)

When SUM is called with a second argument, ... is this second argument and __VA_OPT__ expands to the value given which is a coma. In that case DEF_OR_ARG(__VA_ARGS__ __VA_OPT(,) 5) becomes DEF_OR_ARG(second_argument_of_SUM , 5)

Now the expansion of DEF_OR_ARG happens. This one is easy since it considers only the first argument and just discards the rest. So, when SUM was called with no second argument (first case above), the first argument to DEF_OR_ARG is our default value. In the case there was a second argument to SUM, it becomes the first argument to DEF_OR_ARG that will expand to that and discard the default which is now second argument.

answered May 31, 2012 at 21:13

Comments

7

Try this.

#include <stdio.h>
#include <stdarg.h>
/* print all non-negative args one at a time;
 all args are assumed to be of int type */
void printargs(int arg1, ...)
{
 va_list ap;
 int i;
 va_start(ap, arg1); 
 for (i = arg1; i >= 0; i = va_arg(ap, int))
 printf("%d ", i);
 va_end(ap);
 putchar('\n');
}
int main(void)
{
 printargs(5, 2, 14, 84, 97, 15, 24, 48, -1);
 printargs(84, 51, -1);
 printargs(-1);
 printargs(1, -1);
 return
 0;
}
answered May 7, 2014 at 18:41

Comments

6

There is a way to support as many default parameters you need, just use a structure.

// Populate structure with var list and set any default values
struct FooVars {
 int int_Var1 = 1; // One is the default value
 char char_Command[2] = {"+"};
 float float_Var2 = 10.5;
};
struct FooVars MainStruct;
//...
// Switch out any values needed, leave the rest alone
MainStruct.float_Var2 = 22.8;
Myfunc(MainStruct); // Call the function which at this point will add 1 to 22.8.
//...
void Myfunc( struct FooVars *MyFoo ) {
 switch(MyFoo.char_Command) {
 case '+':
 printf("Result is %i %c %f.1 = %f\n" MyFoo.int_Var1, MyFoo.char_Command, MyFoo.float_Var2, (MyFoo.float_Var2 + MyFoo.int_Var1);
 break;
 case '*':
 // Insert multiply here, you get the point...
 break;
 case '//':
 // Insert divide here...
 break;
 }
}
answered Aug 23, 2012 at 14:47

1 Comment

I'm no C expert, but you can't set default values in a struct like that. Can you?
3

As far as I know ANSI C doesn't directly support function overloading or default arguments. The standard substitute for overloading is adding suffixes to the function name indicating the argument types. For example, in OpenGL, a "3fv" suffix to a function name means the function takes a vector of three floats.

Default arguments can be viewed as a special case of function overloading.

answered Jun 7, 2010 at 8:44

Comments

2

Neither of default values or function overloading exists in ANSI C, so you'll have to solve it in a different way.

answered Jun 7, 2010 at 8:39

Comments

1

You can't so easily since C does not support them. The simpler way to get "fake overloading" is using suffixes as already said... default values could be simulated using variable arguments function, specifying the number of args passed in, and programmatically giving default to missing one, e.g.:

 aType aFunction(int nargs, ...)
 {
 // "initialization" code and vars
 switch(nargs)
 {
 case 0:
 // all to default values... e.g.
 aVar1 = 5; // ...
 break;
 case 1:
 aVar1 = va_arg(arglist, int); //...
 // initialize aVar2, 3, ... to defaults...
 break;
 // ...
 }
 }

Also overloading can be simulated using var args with extra informations to be added and passed and extracode... basically reproducing a minimalist object oriented runtime ... Another solution (or indeed the same but with different approach) could be using tags: each argument is a pair argument type + argument (an union on the whole set of possible argument type), there's a special terminator tag (no need to specify how many args you're passing), and of course you always need "collaboration" from the function you're calling, i.e. it must contain extra code to parse the tags and choose the actual function to be done (it behaves like a sort of dispatcher)

answered Jun 7, 2010 at 9:15

Comments

0

You'll have to declare each C++ overloaded function differently in C because C doesn't do name mangling. In your case "foo_property1" "foo_property2".

answered Jun 7, 2010 at 12:02

Comments

0

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;
}
answered Feb 18 at 15:39

Comments

-1

i think u can use a function with variable arguments here is my example

#include <stdarg.h>
#include <stdio.h>
void baz( int flag, ... )
{
 va_list ap;
 char *bar = "baz"; /* default value */
 va_start( ap, flag );
 if ( flag == 1 )
 bar = va_arg( ap, char * );
 va_end( ap );
 printf( "%s\n", bar );
}
int main( void )
{
 baz( 0 );
 baz( 1, "foo");
 baz( 2 );
 baz( 1, "bar");
 return 0;
}

the output is

baz
foo
baz
bar

if u look for example man 2 open they say

SYNOPSIS
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 int open(const char *pathname, int flags);
 int open(const char *pathname, int flags, mode_t mode);
 int creat(const char *pathname, mode_t mode);
 int openat(int dirfd, const char *pathname, int flags);
 int openat(int dirfd, const char *pathname, int flags, mode_t mode);

but mode is actually a ... argument

answered Feb 27, 2017 at 20:37

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.