2010-04-13 32 views
18

Nếu tôi xác định một số vĩ mô:Looping qua varargs vĩ mô giá trị

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

Có một số cách để thực sự lặp qua args chứ không phải vượt qua nó cùng với chức năng khác? Một cái gì đó như

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

thể trùng lặp của [? Có thể để lặp qua đối số trong macro variadic] (http: // stackoverflow .com/questions/1872220/is-it-possible-to-iterate-over-arguments-in-variadic-macros) –

Trả lời

21

Không phải là tôi có thể nghĩ đến ...

Tuy nhiên, nếu ứng dụng của bạn cho việc này là xử lý một số biến của tham số cùng loại, ví dụ:

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

và bạn không ngại sử dụng một chức năng để giúp đỡ, sau đó có một số thủ thuật hữu ích có thể được thực hiện.

Vấn đề chính ở đây là bạn không thể chuyển các đối số này thẳng đến hàm varargs, vì không có cách nào cho hàm đó để biết có bao nhiêu đối số cần đọc. Và đó là vấn đề thể được giải quyết với một số tiền xử lý ma thuật:

#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; 
} 

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

Câu trả lời chắc chắn toàn diện, cảm ơn bạn. Nhưng tôi nghĩ tôi sẽ không sử dụng phương pháp này :) –

+0

Tôi yêu bộ xử lý trước, nó rất tốt – RichardBruce