3

ゼロ個以上の引数を取る必要がある可変個引数マクロをCで記述する必要があります。

gccでは、これは、コンマの後に「##」を追加することで実現できます。たとえば、引数がゼロの可変個引数マクロで,##____VA_ARGS____回答されます。

ただし、ビルドシステムのコンパイラー(制御不能)は,##構文を理解しないため、コンマを飲み込みません。

使用できる回避策はありますか?

ありがとう!

4

2 に答える 2

4

はい、コンマを飲み込むgccは非標準であり、それに依存するべきではありません。

C99準拠のプリプロセッサを使用すると、空のトークンであるマクロ引数をテストすることで、同様の効果を得ることができます。これがどのように機能するかについては、ここを参照してください。このような機能のプログラミングを容易にするプリプロセッサマクロのセット全体については、P99があります。

于 2011-12-09T12:43:08.893 に答える
1

イェンスが綴った簡略版を使用して、可能なアプローチを以下に説明します。

E_引数を挿入するためにI_使用され、マクロの間接呼び出しを引き起こすために使用されます。一部のコンパイラV_では必要と思われる、追加レベルの間接参照を追加する必要があります。

#define V_(...) __VA_ARGS__
#define I_(M,...) V_(M(__VA_ARGS__))
#define E_() _,

MACここで、 0、1、または2つの引数を処理するマクロが必要だとします。

MAC(1, 2);
MAC(1);
MAC();

考えられる実装の1つは、次のようになります。

#define MAC_X(_2,_1,X,...) MAC_##X
#define MAC(...) V_(V_(MAC_X(__VA_ARGS__,2,_))(__VA_ARGS__))

#define MAC_2(...) function_for_2(__VA_ARGS__)
#define MAC_1(...) function_for_1(__VA_ARGS__)
#define MAC_0(...) function_for_0(__VA_ARGS__)

#define MAC_Y(_1,Y,...) MAC_##Y
#define MAC__(...) I_(MAC_Y, E_ __VA_ARGS__ () 0, 1)(__VA_ARGS__)

そしてそれを3つの引数に拡張することは比較的簡単です。唯一の厄介な点は、1つまたは0つの引数を検出することですが、これは変更されません。

-#define MAC_X(_2,_1,X,...) MAC_##X
-#define MAC(...) V_(V_(MAC_X(__VA_ARGS__,2,_))(__VA_ARGS__))
+#define MAC_X(_3,_2,_1,X,...) MAC_##X
+#define MAC(...) V_(V_(MAC_X(__VA_ARGS__,3,2,_))(__VA_ARGS__))

+#define MAC_3(...) function_for_3(__VA_ARGS__)
 #define MAC_2(...) function_for_2(__VA_ARGS__)

複数の引数の場合、MACマクロはMAC_2(またはMAC_3)に展開されます。ただし、引数が1または0の場合、MACマクロはに展開されMAC__ます。

このMAC__マクロは、Jensのトリックを適用して、1つまたは0つの引数が渡されたかどうかを検出します。これはヘルパーマクロを使用して行い、とのE_間に引数を挿入すると呼び出されます。引数が0の場合、が呼び出され、引数が挿入されます。挿入された引数は、選択するための2番目の引数になります。引数が1つある場合、は展開されません。toへの最初の引数はになり(ここで、は最初の引数が何であれ)、の2番目の引数はです。これにより、またはのいずれかを呼び出すことができます。E_()E_0MAC_YE_MAC_YE_ ... () 0...MAC_Y1MAC_YMAC_0MAC_1

于 2020-01-15T00:52:42.740 に答える