71

私は約30個の可変関数を持っています。それぞれが最後の引数としてパスを受け入れます。例:

bool do_foo(struct *f, int q, const char *fmt, ...)

各関数で、展開された形式が特定のサイズ以下であることを確認する必要があります。そのため、同じコードのチャンクをコピーして貼り付けて、vsnprintf()印刷されなかった文字数を確認し、errnoそれに応じて設定して、書き込みを回避しています。

私がやりたいのは、これを行う関数を作成することです。これは、安全なサイズであることがわかっている静的に割り当てられた (拡張された) 文字列、または失敗時に新しく初期化された文字列を返し、NULL に対してチェックすることができます。チェックでは、文字列が絶対パスか相対パスかを判断する必要もあります。これは、文字列の安全なサイズに影響します。重複コードが多く、臭いがし始めています。

関数のエントリから別の関数に省略記号の内容を渡す方法はありますか? または、最初に呼び出してからヘルパー関数にva_start()渡す必要がありますか?va_list

編集:

ヘルパーにを渡すことにまったく反対しているわけではありva_listません。他に何も存在しないことを確認したかっただけです。コンパイラーは可変引数の開始位置を理解しているように見えるので、それらを渡すようにコンパイラーに指示できるかどうか知りたかっただけです。

4

4 に答える 4

71

できません。引数を として渡すことしかできませんva_listcomp.lang.c FAQを参照してください。

一般に、C で可変個引数関数 (つまり、可変数の引数を取る関数) を作成する場合、各関数の 2 つのバージョンを作成する必要が...ありva_listます。省略記号を取るバージョンは を呼び出しva_start、 を取るバージョンを呼び出し、 をva_list呼び出しva_end、そして戻る必要があります。一方が他方を呼び出すため、関数の 2 つのバージョン間でコードを重複させる必要はありません。

于 2009-03-30T04:21:19.033 に答える
12

おそらく、可変個引数マクロを使用できます-次のように:

#define FOO(...)  do { do_some_checks; myfun(__VA_ARGS__); } while (0)

NB!可変個引数マクロはC99のみです

于 2009-03-30T06:00:03.540 に答える
1

これが役立つかどうかはわかりませんが、参照によって変数にアクセスできます。これは一種の卑劣なトリックですが、残念ながら、最終的な関数定義で省略記号を使用することはできません。

#include <stdio.h>

void print_vars(int *n)
{
  int i;
  for(i=0;i<=*n;i++)
    printf("%X %d  ", (int)(n+i), *(n+i));
  printf("\n");
}

void pass_vars(int n, ...)
{
  print_vars(&n);
}

int main()
{
    pass_vars(4, 6, 7, 8, 0);
    return 0;
}

私のPCでは出力されます

$ ./a.out
BFFEB0B0 4  BFFEB0B4 6  BFFEB0B8 7  BFFEB0BC 8  BFFEB0C0 0
于 2012-06-01T04:53:19.250 に答える
0

va_list をヘルパーに渡す必要があります。

于 2009-03-30T04:15:18.300 に答える