使用省略号的宏中的变量争论

我想定义一个接受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具有布尔类型和常量,因此它们是_Boolboolfalsetrue