2012-07-16 20 views
1

我想定义一个接受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; 
} 
+3

宏参数没有类型... – 2012-07-16 23:47:56

+0

你想什么这样做的论据? – 2012-07-16 23:48:12

回答

0

不要使用宏来做到这一点,请使用variadic function

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不检查是否真的有第二个参数。

此外,使用接受一个或2参数的宏,可使用GCC特技(在this page最底部):

#define PRINT_STRING(should , args...) print_string(should , ##args) 

(注意逗号之间的空间)

+0

对编译时可以解决的问题使用复杂的运行时功能?问题明确要求使用可变宏的解决方案? https://gustedt.wordpress.com/2011/07/10/avoid-writing-va_arg-functions/ – 2012-07-17 07:07:49

+0

这实际上是我在我的答案的第二部分提出的。编写这种宏只是一件容易的事情:例如,他的可变宏就不会编译;我不确定你可以提出比我在商店中更简单的东西... – Gui13 2012-07-17 07:25:42

2

如果你的编译器支持__VA_ARGS__,你可以做这样的:

#include <stdio.h> 

#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! 
+0

太复杂了,只选择1或2个宏参数 – 2012-07-17 07:05:59

+0

@JensGustedt我将问题简化为我知道如何解决的问题。 – 2012-07-17 07:33:09

2

做这样的事情,你就必须实施一系列的宏,这样的事情

#include <stdbool.h> 
#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
+0

你应该使用'while(0)'!否则,事情将无限循环! – Gui13 2012-07-17 07:30:56

+0

@ Gui13,完全谢谢! – 2012-07-17 07:58:43