2012-07-16 49 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