簡體   English   中英

如何在 function 定義和 function 調用中使用可變參數宏 arguments?

[英]How to use variadic macro arguments in both a function definition and a function call?

我正在嘗試使用宏來根據宏的參數定義幾個類似的函數。 然而,生成的 function 需要采用的參數的數量和類型在所有函數中並不相同,但我還需要將所有函數的 arguments 傳遞到函數體內的另一個可變參數 ZC1C425268E68385D1AB4Z5074F'

我正在嘗試完成的一個最小示例:

#define COMMAND(__COMMAND__, __FORMAT__, ...) \
  void __COMMAND__ ( __VA_ARGS__ ) {          \
    printf( __FORMAT__, ##__VA_ARGS__ );      \
  }

COMMAND( Start,        "m start %c\r", (char) unit )
COMMAND( Home,         "m home\r" )
COMMAND( Add_To_Chart, "cv 0 %d %d\r", (int) ch1, (int) ch2 )
// literally hundreds of additional COMMANDs needed here.

(注意function的實際邏輯要復雜得多。)

但是,我無法找出在 function 定義和 function 調用中作為參數列表有效的語法。

使用形式(type)arg不是 function 定義的有效語法,但我可以將它傳遞給printf就好了(它被視為強制轉換)。

COMMAND( A, "cv 0 %d %d\r", (int)ch1, (int)ch2 )
// error: expected declaration specifiers or ‘...’ before ‘(’ token
// void A ( (int)ch1, (int)ch2 ) {
//   printf( "cv 0 %d %d\r", (int)ch1, (int)ch2 );
// }

Doing it the other way, type(arg) , appears to work for the function declaration, but function-style casts are only available in C++, not C, so it fails on printf .

COMMAND( B, "cv 0 %d %d\r", int(ch1), int(ch2) )
// error: expected expression before ‘int’
// void B ( int(ch1), int(ch2) ) {
//   printf( "cv 0 %d %d\r", int(ch1), int(ch2) );
// }

如何使用可變參數宏 arguments 作為函數的參數定義和傳遞給另一個 function 的參數?

不要在代碼中使用__*標識符。 __COMMAND____FORMAT__使您的代碼無效。

你必須讓預處理器知道類型。 將它們作為單獨的令牌傳遞,然后將它們打亂,例如在由 arguments 數量過載的單獨鏈中。

// Create function arguments
#define ARGS_0()            void
#define ARGS_2(t1,v1)        t1 v1
#define ARGS_4(t1,v1,t2,v2)  t1 v1, t2 v2
#define ARGS_N(_4,_3,_2,_1,_0,N,...)   ARGS##N
#define ARGS(...)   ARGS_N(_0,##__VA_ARGS__,_4,_3,_2,_1,_0)(__VA_ARGS__)

// Pass arguments to printf with a leading comma.
#define PASS_0()
#define PASS_2(t1,v1)       , v1        
#define PASS_4(t1,v1,t2,v2) , v1, v2
#define PASS_N(_4,_3,_2,_1,_0,N,...)  PASS##N
#define PASS(...)  PASS_N(_0,##__VA_ARGS__,_4,_3,_2,_1,_0)(__VA_ARGS__)

#define COMMAND(cmd, fmt, ...) \
  void cmd(ARGS(__VA_ARGS__)) { \
    printf(fmt PASS(__VA_ARGS__)); \
  }

COMMAND( Start,        "m start %c\r", char, unit)
COMMAND( Home,         "m home\r")
COMMAND( Add_To_Chart, "cv 0 %d %d\r", int, ch1, int, ch2)

擴展為:

void Start(char unit) { printf("m start %c\r" , unit); }
void Home(void) { printf("m home\r" ); }
void Add_To_Chart(int ch1, int ch2) { printf("cv 0 %d %d\r" , ch1, ch2); }

您可以通過在 arguments 的數量上重載單個“在每對 arguments 上應用宏並將它們與此連接,如果為空則使用此”來使代碼更通用。

#define ESC(...)  __VA_ARGS__

#define APPLYTWOJOIN_0(f,j,e)            ESC e
#define APPLYTWOJOIN_2(f,j,e,t,v)      f(t,v)
#define APPLYTWOJOIN_4(f,j,e,t,v,...)  f(t,v) ESC j \
        APPLYTWOJOIN_2(f,j,e,__VA_ARGS__)
#define APPLYTWOJOIN_6(f,j,e,t,v,...)  f(t,v) ESC j \
        APPLYTWOJOIN_4(f,j,e,__VA_ARGS__)
#define APPLYTWOJOIN_8(f,j,e,t,v,...)  f(t,v) ESC j \
        APPLYTWOJOIN_6(f,j,e,__VA_ARGS__)
// etc.
#define APPLYTWOJOIN_N(_8,_7,_6,_5,_4,_3,_2,_1,_0,N,...)  \
        APPLYTWOJOIN##N
// For every two arguments in the list, apply function `f(a,b)` on it.
// Join every result of that function with `ESC j`.
// Expand empty result to `ESC e`.
#define APPLYTWOJOIN(f, j, e, ...)  \
        APPLYTWOJOIN_N(_0,##__VA_ARGS__,_8,_7,_6,_5,_4,_3,_2,_1,_0)\
        (f,j,e,##__VA_ARGS__)

// Pass argument to printf. The leading comma is after format string.
#define PASS(t,v)  , v
// Pass arguments in function parameter list.
#define ARGS(t,v)  t v

#define COMMAND(cmd, fmt, ...) \
  void cmd( APPLYTWOJOIN(ARGS, (,), (void), ##__VA_ARGS__) ) { \
    printf(fmt APPLYTWOJOIN(PASS, (), (), ##__VA_ARGS__) ); \
  }

COMMAND( Start,        "m start %c\r", char, unit)
COMMAND( Home,         "m home\r")
COMMAND( Add_To_Chart, "cv 0 %d %d\r", int, ch1, int, ch2)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM