Looping through macro Varargs values

后端 未结 1 616
南旧
南旧 2021-02-12 17:12

If I define some macro:

#define foo(args...) ({/*do something*/})

Is there some way to actually loop through args rather than pass

1条回答
  •  借酒劲吻你
    2021-02-12 17:59

    Not that I can think of...

    However, if your application for this is handling a variable number of arguments of the same type, e.g.:

    foo(0);
    foo(10, 20, 30);
    foo(1, 2, 3, 4, 5, 6, 7, 8, 9);
    

    and you don't mind using a function to help, then there is some useful trickery that can be done.

    The main problem here is that you can't just pass these arguments straight to a varargs function, because there's no way for that function to know how many arguments there are to read. And that problem can be solved with some preprocessor magic:

    #include 
    #include 
    
    #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
    
    /* C99-style: anonymous argument referenced by __VA_ARGS__, empty arg not OK */
    
    # define N_ARGS(...) N_ARGS_HELPER1(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
    # define N_ARGS_HELPER1(...) N_ARGS_HELPER2(__VA_ARGS__)
    # define N_ARGS_HELPER2(x1, x2, x3, x4, x5, x6, x7, x8, x9, n, ...) n
    
    # define foo(...) foo_helper(N_ARGS(__VA_ARGS__), __VA_ARGS__)
    
    #elif defined(__GNUC__)
    
    /* GCC-style: named argument, empty arg is OK */
    
    # define N_ARGS(args...) N_ARGS_HELPER1(args, 9, 8, 7, 6, 5, 4, 3, 2, 1)
    # define N_ARGS_HELPER1(args...) N_ARGS_HELPER2(args)
    # define N_ARGS_HELPER2(x1, x2, x3, x4, x5, x6, x7, x8, x9, n, x...) n
    
    # define foo(args...) foo_helper(N_ARGS(args), args)
    
    #else
    
    #error variadic macros for your compiler here
    
    #endif
    
    static inline void foo_helper(unsigned int n_args, ...)
    {
      unsigned int i, arg;
      va_list ap;
    
      va_start(ap, n_args);
      printf("%u argument(s):\n", n_args);
      for (i = 0; i < n_args; i++) {
        arg = va_arg(ap, unsigned int);
        printf("  %u\n", arg);
      }
      va_end(ap);
    }
    
    int main(void)
    {
      foo(0);
      foo(10, 20, 30);
      foo(1, 2, 3, 4, 5, 6, 7, 8, 9);
      return 0;
    }
    

    Output:

    $ gcc -W -Wall -std=c99 -pedantic -o va_macro va_macro.c
    $ ./va_macro
    1 argument(s):
      0
    3 argument(s):
      10
      20
      30
    9 argument(s):
      1
      2
      3
      4
      5
      6
      7
      8
      9
    $ 
    

    0 讨论(0)
提交回复
热议问题