C语言宏 ## __VA_ARGS__

Returns NARG, the number of arguments contained in __VA_ARGS__ before 
expansion as far as NARG is >0 and <64 (cpp limits):

#define PP_RSEQ_N() 63,62,61,60,[..],9,8,7,6,5,4,3,2,1,0

#define PP_ARG_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,[..],_61,_62,_63,N,...) N

#define PP_NARG_(...) PP_ARG_N(__VA_ARGS__)

#define PP_NARG( ...) PP_NARG_(__VA_ARGS__,PP_RSEQ_N())

[..] stands for the continuation of the sequence omitted here for lisibility.

PP_NARG(A) -> 1
PP_NARG(A,B) -> 2
PP_NARG(A,B,C) -> 3
PP_NARG(A,B,C,D) -> 4
PP_NARG(A,B,C,D,E) -> 5
PP_NARG(A1,A2,[..],A62,A63) -> 63
/* The PP_NARG macro returns the number of arguments that have been passed to it. */

#define PP_NARG(...) \
         PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) \
         PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
          _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
         _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
         _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
         _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
         _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
         _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
         _61,_62,_63,N,...) N
#define PP_RSEQ_N() \
         63,62,61,60,                   \
         59,58,57,56,55,54,53,52,51,50, \
         49,48,47,46,45,44,43,42,41,40, \
         39,38,37,36,35,34,33,32,31,30, \
         29,28,27,26,25,24,23,22,21,20, \
         19,18,17,16,15,14,13,12,11,10, \
         9,8,7,6,5,4,3,2,1,0

/* Some test cases */


PP_NARG(A) -> 1
PP_NARG(A,B) -> 2
PP_NARG(A,B,C) -> 3
PP_NARG(A,B,C,D) -> 4
PP_NARG(A,B,C,D,E) -> 5
PP_NARG(1,2,3,4,5,6,7,8,9,0,
         1,2,3,4,5,6,7,8,9,0,
         1,2,3,4,5,6,7,8,9,0,
         1,2,3,4,5,6,7,8,9,0,
         1,2,3,4,5,6,7,8,9,0,
         1,2,3,4,5,6,7,8,9,0,
         1,2,3) -> 63

Note: using PP_NARG() without arguments would violate 6.10.3p4 of ISO C99.

I extended this to also work correctly with 0 arguments (but now it will accept only 62 arguments): 

#define __VA_NARG__(...) \ 
        (__VA_NARG_(_0, ## __VA_ARGS__, __RSEQ_N()) - 1) 
#define __VA_NARG_(...) \ 
        __VA_ARG_N(__VA_ARGS__) 
#define __VA_ARG_N( \ 
         _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ 
        _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ 
        _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ 
        _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ 
        _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ 
        _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ 
        _61,_62,_63,N,...) N 
#define __RSEQ_N() \ 
        63, 62, 61, 60,                         \ 
        59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \ 
        49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \ 
        39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \ 
        29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \ 
        19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \ 
         9,  8,  7,  6,  5,  4,  3,  2,  1,  0 

http://blog.csdn.net/yiya1989/article/details/7849588

#define myprintf(...) printk("[lch]:File:%s, Line:%d, Function:%s," __VA_ARGS__, __FILE__, __LINE__ ,__FUNCTION__);

此处的 #define 的作用是将 myprintf( )换成后面那一大串的内容,而括号内 ... 的内容原样抄写在 __VA_ARGS__ 的位置。最终输出如下:

[lch]:File:arch/arm/mach-omap2/board-omap3wscec-camera.c, Line:163, Function:beagle_cam_init,camera init!

 

1)__VA_ARGS__:总体来说就是将左边宏中 ... 的内容原样抄写在右边 __VA_ARGS__ 所在的位置。
它是一个可变参数的宏,是新的C99规范中新增的,目前似乎只有gcc支持(VC从VC2005开始支持)。
要注意的是,printf 的输出格式是括号内左边是字符串,右边是变量,而且右变量与左输出格式是一一对应的。
所以在上面那个例子中, __VA_ARGS__只能是一些不含任何变量的字符串常量。
因为上面的例子中若__VA_ARGS__含有变量,整个printf的输出与变量便不能一一对应,输出会出错。

如果仅仅是替换函数名,可用如下方式,此时对__VA_ARGS__无任何特殊要求:
#define myprintf(...) printk( __VA_ARGS__),在调试程序时可以这样用:

#ifndef LOG_NDEBUG_FUNCTION
#define LOGFUNC(...) ((void)0)
#else
#define LOGFUNC(...) (printk(__VA_ARGS__))
#endif

2) __FILE__ :宏在预编译时会替换成当前的源文件名
3) __LINE__:宏在预编译时会替换成当前的行号
4) __FUNCTION__:宏在预编译时会替换成当前的函数名称
5)类似的宏还有 __TIME__,__STDC__, __TIMESTAMP__等,就完全当一个变量来使用即可。

宏连接符##:
举个例子:宏定义为
#define XNAME(n) x##n,
代码为:XNAME(4),则在预编译时,宏发现XNAME(4)与XNAME(n)匹配,
则令 n 为 4,然后将右边的n的内容也变为4,然后将整个XNAME(4)替换为 x##n,亦即 x4,故 最终结果为
XNAME(4) 变为 x4.

#include <stdio.h>
#define XNAME(n) x ## n
#define PRINT_XN(n) printf("x" #n " = %d/n", x ## n);
int main(void)
{
int XNAME(1) = 14; // becomes int x1 = 14;
int XNAME(2) = 20; // becomes int x2 = 20;
PRINT_XN(1); // becomes printf("x1 = %d,", x1);
PRINT_XN(2); // becomes printf("x2 = %d/n", x2);
return 0;
}

 

输出为:x1 = 14, x2 = 20

http://stackoverflow.com/questions/2124339/c-preprocessor-va-args-number-of-arguments

 

#include <stdio.h>
#include <string.h>
#include <stdarg.h>

#define NUMARGS(...)  (sizeof((int[]){__VA_ARGS__})/sizeof(int))
#define SUM(...)  (sum(NUMARGS(__VA_ARGS__), __VA_ARGS__))

void sum(int numargs, ...);

int main(int argc, char *argv[]) {

    SUM(1);
    SUM(1, 2);
    SUM(1, 2, 3);
    SUM(1, 2, 3, 4);

    return 1;
}

void sum(int numargs, ...) {
    int     total = 0;
    va_list ap;

    printf("sum() called with %d params:", numargs);
    va_start(ap, numargs);
    while (numargs--)
        total += va_arg(ap, int);
    va_end(ap);

    printf(" %d\n", total);

    return;
}

It is completely valid C99 code. It has one drawback, though -
you cannot invoke the macro SUM() without params, but GCC has a solution to it - see here.
So in case of GCC you need to define macros like this:

#define       NUMARGS(...)  (sizeof((int[]){0, ##__VA_ARGS__})/sizeof(int)-1)
#define       SUM(...)  sum(NUMARGS(__VA_ARGS__), ##__VA_ARGS__)

With msvc extension, Works for 0 - 32 arguments. This limit can be easily extended.

#define Y_TUPLE_SIZE(...) Y_TUPLE_SIZE_II((Y_TUPLE_SIZE_PREFIX_ ## __VA_ARGS__ ## _Y_TUPLE_SIZE_POSTFIX,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))
#define Y_TUPLE_SIZE_II(__args) Y_TUPLE_SIZE_I __args

#define Y_TUPLE_SIZE_PREFIX__Y_TUPLE_SIZE_POSTFIX ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0

#define Y_TUPLE_SIZE_I(__p0,__p1,__p2,__p3,__p4,__p5,__p6,__p7,__p8,__p9,__p10,__p11,__p12,__p13,__p14,__p15,__p16,__p17,__p18,__p19,__p20,__p21,__p22,__p23,__p24,__p25,__p26,__p27,__p28,__p29,__p30,__p31,__n,...) __n

 

http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html

A macro can be declared to accept a variable number of arguments much as a function can. The syntax for defining the macro is similar to that of a function.
Here is an example:

 #define eprintf(...) fprintf (stderr, __VA_ARGS__)

 

This kind of macro is called variadic. When the macro is invoked, all the tokens in its argument list after the last named argument (this macro has none),
including any commas, become the variable argument. This sequence of tokens replaces the identifier __VA_ARGS__in the macro body wherever it appears.
Thus, we have this expansion:

     eprintf (        "%s:%d: ", input_file, lineno)
==>  fprintf (stderr, "%s:%d: ", input_file, lineno)

 

The variable argument is completely macro-expanded before it is inserted into the macro expansion, just like an ordinary argument.
You may use the ‘#’ and ‘##’ operators to stringify the variable argument or to paste its leading or trailing token with another token.
(But see below for an important special case for ‘##’.)

If your macro is complicated, you may want a more descriptive name for the variable argument than __VA_ARGS__.
CPP permits this, as an extension. You may write an argument name immediately before the ‘...’;
that name is used for the variable argument. The eprintf macro above could be written

#define eprintf(args...) fprintf (stderr, args)

 

using this extension. You cannot use __VA_ARGS__ and this extension in the same macro.

You can have named arguments as well as variable arguments in a variadic macro. We could define eprintf like this, instead:

 #define eprintf(format, ...) fprintf (stderr, format, __VA_ARGS__)

This formulation looks more descriptive, but unfortunately it is less flexible:
you must now supply at least one argument after the format string.
In standard C, you cannot omit the comma separating the named argument from the variable arguments.
Furthermore, if you leave the variable argument empty, you will get a syntax error,
because there will be an extra comma after the format string.

    eprintf(        "success!\n", );
==> fprintf(stderr, "success!\n", );

GNU CPP has a pair of extensions which deal with this problem. First, you are allowed to leave the variable argument out entirely:

    eprintf (       "success!\n")
==> fprintf(stderr, "success!\n", );

 

Second, the ‘##’ token paste operator has a special meaning when placed between a comma and a variable argument. If you write

#define eprintf(format, ...) fprintf (stderr, format, ##__VA_ARGS__)

and the variable argument is left out when the eprintf macro is used, then the comma before the ‘##’ will be deleted.
This does not happen if you pass an empty argument, nor does it happen if the token preceding ‘##’ is anything other than a comma.

    eprintf (       "success!\n")
==> fprintf(stderr, "success!\n");

 

The above explanation is ambiguous about the case where the only macro parameter is a variable arguments parameter,
as it is meaningless to try to distinguish whether no argument at all is an empty argument or a missing argument.
In this case the C99 standard is clear that the comma must remain, however the existing GCC extension used to swallow the comma.
So CPP retains the comma when conforming to a specific C standard, and drops it otherwise.

C99 mandates that the only place the identifier __VA_ARGS__ can appear is in the replacement list of a variadic macro.
It may not be used as a macro name, macro argument name, or within a different type of macro.
It may also be forbidden in open text; the standard is ambiguous.
We recommend you avoid using it except for its defined purpose.

Variadic macros are a new feature in C99. GNU CPP has supported them for a long time,
but only with a named variable argument (‘args...’, not ‘...’ and __VA_ARGS__).
If you are concerned with portability to previous versions of GCC, you should use only named variable arguments.
On the other hand, if you are concerned with portability to other conforming implementations of C99, you should use only __VA_ARGS__.

Previous versions of CPP implemented the comma-deletion extension much more generally.
We have restricted it in this release to minimize the differences from C99.
To get the same effect with both this and previous versions of GCC, the token preceding the special ‘##’ must be a comma,
and there must be white space between that comma and whatever comes immediately before it:

#define eprintf(format, args...) fprintf (stderr, format , ##args)

 

http://en.wikipedia.org/wiki/Variadic_macro

Variadic macro

variadic macro is a feature of some computer programming languages, especially the C preprocessor,
whereby a macro may be declared to accept a varying number of arguments.

Variable-argument macros were introduced in 1999 in the ISO/IEC 9899:1999 (C99) revision of the C language standard,
and in 2011 in ISO/IEC 14882:2011 (C++11) revision of the C++ language standard.[1]

Declaration syntax 

The declaration syntax is similar to that of variadic functions:
an ellipsis "..." is used to indicate that one or more arguments must be passed.
Common compilers also permit passing zero arguments to such a macro,
however.[2][3] During macro expansion each occurrence of the special identifier __VA_ARGS__ 
in the macro replacement list is replaced by the passed arguments.

No means is provided to access individual arguments in the variable argument list,
nor to find out how many were passed.
However, macros can be written to count the number of arguments that have been passed.[4]

Support 

Several compilers support variable-argument macros when compiling C and C++ code: the GNU Compiler Collection 3.0,[2] Visual Studio 2005,[3]C++Builder 2006, and Oracle Solaris Studio (formerly Sun Studio) Forte Developer 6 update 2 (C++ version 5.3).[5] GCC also supports such macros when compiling Objective-C.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值