【问题标题】:Looping through macro Varargs values循环通过宏 Varargs 值
【发布时间】:2011-02-07 14:32:18
【问题描述】:

如果我定义一些宏:

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

有没有办法真正循环通过args 而不是将它传递给另一个函数?类似的东西

#define foo(args...) \
        { \
           for (int i = 0; i < sizeof(args); ++i) { \
             /*do something with args[i]*/ \
           } \
         }

【问题讨论】:

标签: c macros variadic-functions


【解决方案1】:

我想不到……

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

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
$ 

【讨论】:

  • 一个肯定全面的答案,谢谢。但我想我会避免使用这种方法:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-24
相关资源
最近更新 更多