Default values on arguments in C functions and function overloading in C

前端 未结 9 2053
再見小時候
再見小時候 2020-12-09 09:46

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

9条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-09 09:54

    Nevertheless I found a "trick" to do so if you use GCC.

    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 
    
    
    #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.

提交回复
热议问题