操纵可变参数的标准方法?

Jay*_*rod 7 c variadic-functions

这是一个奇怪的问题,但是va_list在将它传递给另一个函数之前是否有一种标准方法来操作a的内容?例如,假设我有两个函数,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;
}
Run Code Online (Sandbox Code Playgroud)

如果我调用sumas 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);
}
Run Code Online (Sandbox Code Playgroud)

现在当我调用时sum(4, 1, 2, 3, 4),我应该返回结果20,因为vsum_stub增加了2中的所有值va_list.当然不能编译,因为你不能得到结果的地址va_arg.有没有另外一种方法可以做到这一点?我在C99工作.


背景:

我正在开发一个执行指针转换的库,以便数据可以以更有效的格式存储在堆上.程序使用自定义转换进行编译,该转换将对函数的调用转换printf为我自己的存根函数(例如,hc_printf).在将参数传递给真实函数之前,hc_printf需要翻译任何指针参数(用于的字符串%s)printf.

编辑:这是一个代码示例.假设我们有一个字符串foo.foo动态分配的修改版本malloc返回假指针.编译器修改程序,以便它可以处理假指针.这样可行:

char *foo = fake_malloc(4);
fake_strcpy(foo, "foo");
Run Code Online (Sandbox Code Playgroud)

我想写一个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);
}
Run Code Online (Sandbox Code Playgroud)

该程序将fake_vprintfvprintf使用假指针一样调用原始程序.fake_vprintf将假指针转换为真实vprintf可以使用的真实指针.

dir*_*tly 3

啊哈,据我了解,您的问题是创建一个新的va_list参数来传递给标准vprintf函数。这反过来又要求您修改列表中的每个成员。但是,由于这样的列表没有元素明智的获取/编辑/插入操作,因此您陷入困境。

我真的看不出有什么办法可以做到这一点。当然,您可以创建一个原位vprintf应用转换,一次一个参数。我的建议是:重新实现所有此类标准库函数——无论如何,您正在编写包装器。这涉及到一些工作,但是您已经使用 etc 完成了其中的一部分,所以为什么不走完全程(猜猜函数调用会节省什么!)。hc_printf