Это странный вопрос, но есть ли стандартный способ манипулирования содержимым va_list
перед передачей его другой функции? Например, предположим, у меня есть две функции, 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
как 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);
}
Теперь, когда я вызываю sum(4, 1, 2, 3, 4)
, я должен получить результат 20, поскольку vsum_stub
увеличивает все значения в va_list
на 2. Конечно, это не компилируется, так как вы не можете взять адрес результата va_arg
. Есть ли другой способ сделать это? Я работаю в C99.
Справка:
Я работаю над библиотекой, которая выполняет перевод некоторых указателей, чтобы данные могли храниться в куче в более эффективном формате. Программы компилируются с помощью специального преобразования, которое преобразует вызовы библиотечных функций, таких как printf
, в мои собственные функции-заглушки (например, hc_printf
). hc_printf
необходимо перевести все аргументы указателя (строки, предназначенные для %s
) перед передачей аргументов в реальную функцию printf
.
Редактировать: Вот пример кода. Допустим, у нас есть строка 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
.