現在、関数に渡される引数の合計サイズをバイト単位で計算しようとしています。sizeof(x)
理論的には、すべての引数について書き出すことができます。ただし、多くの機能でこれを実行したい場合、これは非常に時間の無駄です。引数のスペースの量を把握して、適切な量のメモリを割り当ててすべてを格納し、格納できるようにしようとしています(さまざまな関数の場合、タイプが混在しています)。
名前や数に関係なく、非可変個引数関数のすべての引数のサイズを決定できる式を作成しようとしています(理由の範囲内で、今のところ約64個の引数のみをサポートしても問題ありません)。 )。それは関数、プリプロセッサマクロである可能性があり、私は実装にとらわれません。可変個引数関数の処理にも興味がありますが、可変個引数関数に入るまでにデータ型に関するすべての情報が失われているため、それは不可能だと確信しています。
現在、私はこれを可能にするためにねじれるかもしれない3つのアプローチを見つけました。1つ目は、 LaurentDeniauの引数カウントの概念に基づいています。理論的には、マクロを使用して関数ヘッダーを生成し、同様の凝ったフットワークを実行して、引数の数を取得し、N個の引数がある個々のケースを処理するさまざまなマクロにディスパッチできます。(参照:醜い)。基本的には、マクロを使用してすべての関数名をエイリアスし、それぞれにsizeofを使用します。問題は、表現したいすべての長さの引数に対してマクロを作成する必要があるということです。そして、私は1つの仕事をするために64(またはそれ以上)のものを作ることを本当に好まない。
2番目のアプローチは、BenKlemerの「より優れた可変個引数」のもののアプローチに従うことを試みることです。私は彼のアプローチのすべてを使用するわけではありませんが、関数のargシグニチャを構造体に表す構造体を生成しようとしています。次に、構造要素のサイズを取得することを試みることができます(または、スペースの控えめな見積もりだけを気にした場合は、構造自体も)。これにはいくつかの問題があります。まず、C99準拠のものでのみ機能する可能性があります(まだそれをチェックしています)。次に、実装されるすべての関数に追加の構造を作成します。これは完全に問題ではありませんが、構造体を作成する彼のアプローチが関数と同じ名前になるという問題があります(したがって、それらを使用するには名前を参照する必要があります)。
可能な3番目のアプローチは再帰マクロですが、それがコンパイラーをどれほど満足させるかはわかりません。理論的には、形式でマクロを呼び出すことにより、 VA_ARGSから要素を再帰的にポップすることができます。明らかに、 VA_ARGが空の場合の停止ルール(およびフローティング+記号に引っ掛からないようにするための何か)が必要ですが、あなたはその考えを理解します。POPPER(arg, ...) POPPER(VA_ARGS) + sizeof(arg)
これらのいずれかを使用すると、これを実行できます。
- 可変個引数マクロからVA_ARGSを解凍するための優れた柔軟な方法。インデックスを作成する方法がある場合
- これを行うために信頼できる再帰マクロの良い例(および引数の最大数、コンパイラの互換性、標準への準拠などの制限)。
- さまざまなタイプの関数検査を通じて、すべての引数の合計サイズを直接取得する方法。GCCには、適用可能なコール転送の関数呼び出しを作成するためのいくつかのクレイジーな関数があるようですが、これらはコンパイラ固有であり、ほとんど文書化されておらず、割り当てられたメモリブロックのサイズを報告していないようです。彼らはまた、無関係な情報を大量に報告します。