操作可变参数的标准方法? [英] Standard way to manipulate variadic arguments?

查看:26
本文介绍了操作可变参数的标准方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个奇怪的问题,但是在将 va_list 的内容传递给另一个函数之前,是否有一种标准的方法来操纵它的内容?例如,假设我有两个函数,sumvsum:

This is a weird question, but is there a standard way to manipulate the contents of a va_list before passing it to another function? For instance, suppose I have two functions, sum and 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 执行以下操作:

If I call sum as sum(4, 1, 2, 3, 4), I expect to get the result 10. Now let's suppose that instead of calling vsum directly, sum calls an intermediate function, vsum_stub which does the following:

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 工作.

Now when I call sum(4, 1, 2, 3, 4), I should get back the result 20, since vsum_stub increments all of the values in the va_list by 2. This doesn't compile of course since you can't take the address of the result of va_arg. Is there another way to do this though? I'm working in C99.

背景:

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

I'm working on a library that does some pointer translation so that data may be stored on the heap in a more efficient format. Programs are compiled with a custom transformation which converts calls to library functions like printf to my own stub functions (e.g., hc_printf). hc_printf needs to translate any pointer arguments (strings intended for %s) before passing the arguments to the real printf function.

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

Here's a code example. Let's say we have a string foo. foo is dynamically allocated with a modified version of malloc which returns a fake pointer. The compiler modifies the program so that it can deal with fake pointers. So this works:

char *foo = fake_malloc(4);
fake_strcpy(foo, "foo");

我想写一个这样的 fake_vprintf 函数(用伪代码):

I want to write a fake_vprintf function like this (in pseudocode):

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 可以使用的真实指针.

The program would call fake_vprintf just like the original vprintf using the fake pointer. fake_vprintf translates the fake pointer to a real pointer that the real vprintf can use.

推荐答案

啊哈,据我所知,您的问题是创建一个新的 va_list 参数以传递给标准 vprintf函数.反过来,这将要求您修改列表中的每个成员.但是,由于没有针对此类列表的元素明智的提取/编辑/插入操作,因此您会陷入困境.

Aha, as I understand, your problem is creating a new va_list argument to pass on to the standard vprintf functions. Which in turn, will require you to modify each member of the list. However, since there is no element wise fetch/edit/insert operation for such a list you are stuck.

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

I don't really see any way of doing this. Of course, you can create a vprintf apply the transformations in situ, one argument at a time. My suggestion will be: Reimplement all such standard library functions -- at any rate you are writing wrappers. This involves some work, but you are already doing a part of it with hc_printf etc, so why not go the whole distance (and guess what save on a function call!).

这篇关于操作可变参数的标准方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆