web-dev-qa-db-ja.com

省略記号を別の可変長関数に渡す

約30個の可変機能を持っています。それぞれが最後の引数としてパスを受け入れます、例えば:

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

各関数で、拡張形式が特定のサイズ以下であることを確認する必要があります。そのため、同じコードチャンクをコピー/ペーストして、vsnprintf()が印刷しなかった文字数を確認し、それに応じてerrnoを設定し、書き込みを終了します。

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

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

編集:

_va_list_をヘルパーに渡すことにまったく反対していません。他に何も存在しないことを確認したかっただけです。可変長引数がどこから始まるかはコンパイラーが理解しているように思えるので、引数を渡すように指示できたら興味がありました。

66
Tim Post

va_listとしてのみ引数を渡すことができません。 comp.lang.c FAQ を参照してください。

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

69
Adam Rosenfield

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

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

NB!可変長マクロはC99のみです

10
qrdl

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

#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
1
Sepero

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

0
Andrew Grant