是的,你可以做到,但它有点难看,你必须知道参数的最大数量。此外,如果您使用的架构不像 x86(例如,PowerPC)那样在堆栈上传递参数,您将必须知道是否使用“特殊”类型(double、float、altivec 等)以及是否使用所以,相应地处理它们。这可能很快就会很痛苦,但如果您使用的是 x86,或者如果原始函数具有明确定义且有限的边界,则它可以工作。
它仍然是一个 hack,用于调试目的。不要围绕它构建你的软件。无论如何,这是一个关于 x86 的工作示例:
#include <stdio.h>
#include <stdarg.h>
int old_variadic_function(int n, ...)
{
va_list args;
int i = 0;
va_start(args, n);
if(i++<n) printf("arg %d is 0x%x\n", i, va_arg(args, int));
if(i++<n) printf("arg %d is %g\n", i, va_arg(args, double));
if(i++<n) printf("arg %d is %g\n", i, va_arg(args, double));
va_end(args);
return n;
}
int old_variadic_function_wrapper(int n, ...)
{
va_list args;
int a1;
int a2;
int a3;
int a4;
int a5;
int a6;
int a7;
int a8;
/* Do some work, possibly with another va_list to access arguments */
/* Work done */
va_start(args, n);
a1 = va_arg(args, int);
a2 = va_arg(args, int);
a3 = va_arg(args, int);
a4 = va_arg(args, int);
a5 = va_arg(args, int);
a6 = va_arg(args, int);
a7 = va_arg(args, int);
va_end(args);
return old_variadic_function(n, a1, a2, a3, a4, a5, a6, a7, a8);
}
int main(void)
{
printf("Call 1: 1, 0x123\n");
old_variadic_function(1, 0x123);
printf("Call 2: 2, 0x456, 1.234\n");
old_variadic_function(2, 0x456, 1.234);
printf("Call 3: 3, 0x456, 4.456, 7.789\n");
old_variadic_function(3, 0x456, 4.456, 7.789);
printf("Wrapped call 1: 1, 0x123\n");
old_variadic_function_wrapper(1, 0x123);
printf("Wrapped call 2: 2, 0x456, 1.234\n");
old_variadic_function_wrapper(2, 0x456, 1.234);
printf("Wrapped call 3: 3, 0x456, 4.456, 7.789\n");
old_variadic_function_wrapper(3, 0x456, 4.456, 7.789);
return 0;
}
出于某种原因,您不能将浮点数与 va_arg 一起使用,gcc 表示它们已转换为双精度,但程序崩溃了。仅此一项就表明该解决方案是一种 hack,并且没有通用解决方案。在我的示例中,我假设参数的最大数量为 8,但您可以增加该数量。包装函数也只使用整数,但它与其他“普通”参数的工作方式相同,因为它们总是转换为整数。目标函数将知道它们的类型,但您的中间包装器不需要。包装器也不需要知道正确数量的参数,因为目标函数也会知道它。要进行有用的工作(除了记录通话),您可能必须同时了解两者。