使用省略号的宏中的变量争论
我想定义一个接受1或2个参数的宏。 两个参数都应该是不同的类型。 如何使用省略号并读取传递的参数?
以下是样本:
void test(char *var2) { printf("%s\n",var2); } #define PRINT_STRING(...) ( if (!var1) test(var2) ) int main(int argc, _TCHAR argv[]) { PRINT_STRING(TRUE); PRINT_STRING(FALSE,"Hello, World!"); return 0; }
不要使用宏来执行此操作,请使用可变参数函数 !
void print_string( bool should_print, ... ) { if( should_print ) { va_list argp; va_start( argp, should_print); char *string = va_arg(argp, char *); if( string) printf("%s", string ); va_end( argp ); } }
但是在使用这些东西时要非常小心,因为va_arg不会检查你是否确实有第二个参数。
另外,要使用接受一个或两个参数的宏,请使用GCC技巧(在本页的最底部):
#define PRINT_STRING( should , args... ) print_string( should , ##args )
(注意逗号之间的空格)
这被称为Variadic宏 。
如果你的编译器支持__VA_ARGS__
,你可以这样做:
#include #define NUM_ARGS__(X, \ N64,N63,N62,N61,N60, \ N59,N58,N57,N56,N55,N54,N53,N52,N51,N50, \ N49,N48,N47,N46,N45,N44,N43,N42,N41,N40, \ N39,N38,N37,N36,N35,N34,N33,N32,N31,N30, \ N29,N28,N27,N26,N25,N24,N23,N22,N21,N20, \ N19,N18,N17,N16,N15,N14,N13,N12,N11,N10, \ N09,N08,N07,N06,N05,N04,N03,N02,N01, N, ...) N #define NUM_ARGS(...) \ NUM_ARGS__(0, __VA_ARGS__, \ 64,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) #define PRINT_STRING_1(var) \ { if (!(var)) {} } #define PRINT_STRING_2(var, ...) \ { if (!(var)) test(__VA_ARGS__); } #define PRINT_STRINGN__(N, ...) \ PRINT_STRING_##N(__VA_ARGS__) #define PRINT_STRINGN(N, ...) \ PRINT_STRINGN__(N, __VA_ARGS__) #define PRINT_STRING(...) \ PRINT_STRINGN(NUM_ARGS(__VA_ARGS__), __VA_ARGS__) void test(char* var2) { printf("%s\n", var2); } int main(void) { PRINT_STRING(1); PRINT_STRING(0, "Hello, World!"); PRINT_STRING(1, "You can't see me!"); return 0; }
输出:
Hello, World!
要做类似的事情,你必须实现一系列的宏,就像这样
#include #define PRINT_STRING0(X, Y) do { if (X && Y) test(Y); } while(false) #define PRINT_STRING1(X, Y, ...) PRINT_STRING0(X, Y) #define PRINT_STRING(...) PRINT_STRING1(__VA_ARGS__, 0, 0)
最后一个(用户界面)添加第二个或第三个参数0
。 然后PRINT_STRING1
忽略所有超过2
参数。 然后PRINT_STRING0
完成工作。
还有一些评论:
- 要小心,像你想要在这里编程的宏可以在语法上放置,就像任何其他语句一样。 在这里的示例中,
do { } while(false)
执行该操作 - 由于C99具有布尔类型和常量,因此它们是
_Bool
或bool
,false
和true