繁体   English   中英

C / C ++ va_arg - 有没有办法跳过一个参数?

[英]C/C++ va_arg - Is there a way to skip an argument?

我想为sprintf()添加功能。 具体来说,我希望能够将自己的POD数据类型传递给它,但我不确定如何执行此操作。

据说,如果你创建了va_list,你可以把它传递给vsprintf()并让它为你做艰苦的工作 - 但我仍然需要访问va_list,并在将va_list传递给vsprintf()之前自己提取项目。

例如,假设以下代码:

struct mypod {
    int somedata;
}; // just for example, you know

// somewhere else in the code...
mypod mp;
mp.somedata = 5325;
my_sprintf(myChrPtr, "%z", mp);

新的%z代码对应于我的新数据类型。

我知道只有指针和POD结构才能通过,这没什么大不了的。 我想知道,如果我到达va_list的末尾(通过使用va_arg()获取args然后将其传递给vsprintf())会发生什么?

谢谢!

制作两个va_list并只使用一个来做你需要做的事情,然后将另一个传递给vsprintf或其他:

va_list l1 = va_start(final_arg);
va_list l2 = va_start(final_arg);

// do stuff with l1 and l2 will be unaffected

vsprintf(/*using l2*/);

请记住,va_list实际上只是指向堆栈上某个位置的指针(我猜这是特定于实现的,但这就是我来自哪里)。 va_arg返回被转换为指定类型的va_list指向的东西,并通过sizeof(thetype)递增指针。 因此,如果你得到两个指针并保持一个而不修改它,你可以将它传递给另一个函数。

我希望我没有误解这个问题。

鉴于必须以正确的顺序调用va_arg并使用正确的类型来确保正确的行为,我认为你必须在处理你关心的部分并将其余的部分传递给vsprintf使用fmt零碎:

void
mysprintf(char *dst, char *fmt, ...)
{
    char *p = fmt;
    va_list va;

    va_start(va, fmt);
    do {
        char *q = strchr(p, '|');
        if (q) {
            /* really should take const char *fmt and not write on it like this... */
            *q++ = '\0';
        }
        dst += vsprintf(dst, p, va);  /* let vsprintf do a subset */
        if (q) {
            dst += sprintf(dst, "%d", va_arg(va, int));  /* consume 1 int */
        }
        p = q;
    } while (p);

    va_end(va);
}


strcpy(fmt, "%s|%s|%s");  /* mutable fmt */
mysprintf(buf, fmt, "hello", 7, "world", 8, "!");

在我的例子中,我刚刚接受了| 就像%d但是附加%...转义的真实例子将会复杂得多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM