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
A 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.