代码之家  ›  专栏  ›  技术社区  ›  Ed Marty

循环宏varargs值

  •  18
  • Ed Marty  · 技术社区  · 15 年前

    如果我定义了一些宏:

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

    有什么方法可以循环通过吗 args 而不是把它传递给另一个函数?有点像

    #define foo(args...) \
            { \
               for (int i = 0; i < sizeof(args); ++i) { \
                 /*do something with args[i]*/ \
               } \
             }
    
    1 回复  |  直到 6 年前
        1
  •  21
  •   Matthew Slattery    15 年前

    我想不出…

    但是,如果您的应用程序正在处理同一类型的可变数量的参数,例如:

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

    你不介意用一个函数来帮助你,然后有一些有用的技巧可以做。

    这里的主要问题是,不能将这些参数直接传递给varargs函数,因为该函数无法知道要读取多少参数。还有那个问题 可以 用一些预处理器魔法解决:

    #include <stdio.h>
    #include <stdarg.h>
    
    #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;
    }
    

    输出:

    $ 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
    $