可変個引数関数があるとしましょう。foo関数foo(int tmp, ...)
を呼び出すときは、引数がいくつあるかを知る必要があります。私は、引数がいくつあるかを知る2つの方法を知っています。
fooを呼び出すときは、-1のように最後の引数を使用します。これにより、関数呼び出しは次のようになり
foo(tmp, 1, 2, 9, -1)
ます。foo内にいて、va_arg呼び出しが-1を返す場合、すべての関数引数を読んだことがわかります。プログラマーが引数の総数を持つfooにもう1つの引数を追加すると、次のようにfooが呼び出されます。
foo(tmp, 5, 1, 2, 3, 4, 5)
またはfoo(tmp, 2, 7, 8)
私は最初の方法をたどっていましたが、かつて次のバグがありました。コードで:
expr_of_type(expr, boolexpr_e, newtable_e, nil_e, -1)
ここで、expr_of_typeは可変個引数関数であり、expr(最初の引数)が次のタイプのいずれかであるかどうかをチェックしていました(boolexpr_eまたはnew_table_eまたはnil_eはすべてのタイプの列挙型でした)。私は誤って書いた:
expr_of_type(expr, boolexpr_e, newtable_e, nil_e -1)
nil_eと-1の間のコンマを忘れました。これは、nil_eが列挙型であり、nil_e -1が有効な式であり、nil_eが0ではなかったため、expr_of_type引数を取得しようとしたときに、指定された可変個引数が最後の引数として-1を検出しなかったためです。検索を続けてバグを作成しましたが、見つけるのに少し時間がかかりました。
可変個引数関数にもう1つの引数を追加または削除するときは、引数の総数を含むパラメーターを変更する必要があるため、2番目の方法も適切ではありません。
可変個引数関数を使用/作成するためのより良い方法を探しているときに、最初の方法を使用したときに発生したバグを解決できる可変個引数マクロを見つけました。ただし、可変個引数マクロはC99標準で使用できます。C89で可変個引数関数を使用/作成するためのより良い方法を探していました。何か案は?