これは奇妙な質問ですが、va_list
別の関数に渡す前に a の内容を操作する標準的な方法はありますか? たとえば、次の 2 つの関数があるsum
としvsum
ます。
int vsum(int n, va_list ap) {
int total = 0;
for (int i = 0; i < n; ++i) {
total += va_arg(n, int);
return total;
}
int sum(int n, ...) {
va_list ap;
va_start(ap, n);
int total = vsum(n, ap);
va_end(ap);
return total;
}
sum
asを呼び出すとsum(4, 1, 2, 3, 4)
、結果は 10 になると予想されます。ここで、vsum
直接呼び出すのではなく、次の処理をsum
行う中間関数を呼び出すとします。vsum_stub
int vsum_stub(int n, va_list ap) {
va_list temp_ap;
va_copy(temp_ap, ap);
for (int i = 0; i < n; ++i) {
int *arg = &va_arg(ap, int);
*arg += 2;
}
va_end(temp_ap);
return vsum(n, ap);
}
を呼び出すと、のすべての値が 2 ずつインクリメントさsum(4, 1, 2, 3, 4)
れるため、結果 20 が返されるはずです。の結果のアドレスを取得できないため、これはもちろんコンパイルされません。これを行う別の方法はありますか?私はC99で働いています。vsum_stub
va_list
va_arg
バックグラウンド:
データをより効率的な形式でヒープに格納できるように、ポインター変換を行うライブラリに取り組んでいます。printf
プログラムは、独自のスタブ関数 (例: )などのライブラリ関数への呼び出しを変換するカスタム変換を使用してコンパイルされますhc_printf
。引数を実際の関数に渡す前にhc_printf
、ポインター引数 ( を対象とした文字列) を変換する必要があります。%s
printf
編集:これはコード例です。string があるとしましょうfoo
。偽のポインターを返すfoo
変更されたバージョンで動的に割り当てられます。malloc
コンパイラは、偽のポインターを処理できるようにプログラムを変更します。したがって、これは機能します:
char *foo = fake_malloc(4);
fake_strcpy(foo, "foo");
fake_vprintf
このような関数を(疑似コードで)書きたいと思います:
int fake_vprintf(const char *format, va_list args) {
for each pointer argument p in args
translate p to q, a real pointer to contiguous memory
replace p with q in args
}
return vprintf(format, args);
}
プログラムは、偽のポインターを使用してfake_vprintf
、オリジナルと同じように呼び出します。偽のポインターを、本物が使用できる本物のポインターに変換します。vprintf
fake_vprintf
vprintf