背景:ここに投稿できない私のコードは、最終的にはマイクロコントローラーで実行されます。マクロは、1つのマクロ定義メカニズムを介して複数のピン定義関数を作成する方法を提供するだけです。私はwindowsとgccを使ってそれらを実験しています。
私は可能な限り問題を抽象化しようとしました。stdコンソール関数を使用しているので、コンソールウィンドウに表示すると便利です。そのため、ファイルを.cppとして保存し、Windowsでg ++を使用してコンパイルします。
次のようにコードを設定したとします。
#define MACRO2(_x) foo##_x(_x)
#define MACRO1(_x) MACRO2(_x)
#define BAR 3
void fooBAR(int num)
{
std::cout << num << std::endl;
}
次のコードを実行した場合(実際の例)
int main()
{
MACRO2(BAR);
return 0;
}
最初にBARが## _ xに挿入され、呼び出される関数名が定義されます。次に、BARがその関数の引数として挿入され、その値に展開されるため、fooBAR(3)が取得されます。コードは機能し、エラーはありません。
ここで、間にマクロを追加しようとすると(これは、私が入ることができない理由で直面している現実の状況です)、私のコードは次のようになります。
int main()
{
MACRO1(BAR);
return 0;
}
しかし、このコードはエラーをスローします。これは、MACRO1(BAR)がMACRO2(BAR)に置き換えられると、(BAR)が3に展開され、MACRO2(3)がfoo3(3)につながるためです。これは、によって確認されています。エラーログ:
エラー:「foo3」はこのスコープで宣言されていません
したがって、要件は次のとおりです。
- BARをMACRO1に渡す必要があり、展開せずにMACRO2に渡す必要があります
- BARという単語はそのままにしておく必要があります。展開を防ぐために##を使用できることはわかっていますが、BARに文字を追加する必要があり、関数呼び出しが機能しなくなります。
どういうわけかこれを成し遂げることは可能ですか?プロセスで最初のマクロを展開せずに、マクロを引数として別のマクロに渡しますか?
ただし、このコードはエラーをスローします。これは、MACRO1(BAR)がMACRO2(BAR)に置き換えられると、(BAR)が3に展開され、MACRO2(3)がfoo3(3)につながるためです。
はい。これは、特定のマクロセットに対して指定されたプリプロセッサの動作です。
それらが識別された後、関数のようなマクロへの引数は、##
または#
プリプロセッサ演算子のオペランドである場合を除いて、マクロの置換テキストに置換される前に完全にマクロ展開されます。これらの演算子の出現が評価され、結果のテキストが、必要に応じて後続のテキストとともに再スキャンされ、追加のマクロが展開されます。
どういうわけかこれを成し遂げることは可能ですか?プロセスで最初のマクロを展開せずに、マクロを引数として別のマクロに渡しますか?
引数が##
or#
演算子のオペランドである場合のみ。後者は役に立ちませんが、前者には回避策があります。必要な引数を変更せずに連結を実行できるように、追加の空の引数を渡すことができます。
#define MACRO2(_x) foo##_x(_x)
#define MACRO1(_x,dummy) MACRO2(_x##dummy)
#define BAR 3
int main()
{
MACRO1(BAR,);
return 0;
}
それはに拡大します
int main()
{
fooBAR(3);
return 0;
}
余分なコンマを避けたい場合は、MACRO1
可変個引数を作成することでそれを行うことができます。
#define MACRO2(_x) foo##_x(_x)
#define MACRO1(_x,...) MACRO2(_x##__VA_ARGS__)
#define BAR 3
int main()
{
MACRO1(BAR);
return 0;
}
それは他のものと同じものに拡大します。
これらのアプローチはどちらも、最上位のマクロに不要な追加の引数値を提供することにより、エラーが発生する可能性があることに注意してください。おそらく、このようなエラーのほとんどはコンパイル時にキャッチされると思われます。これは、拡張によって、質問の試みのようにコードが壊れてしまうためです。しかし、そのようなエラーが偶然に有効であるが間違っているものに拡大する可能性を排除することは困難です。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加