我想为 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()) 获取参数,然后将其传递给 vsprintf() 会发生什么?
谢谢!
鉴于必须以正确的顺序调用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++ = ' ';
}
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
但是具有额外%...
逃逸的真实示例将要复杂得多。
做两个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)
。因此,如果您获得两个指针并保留一个而不对其进行修改,则可以将其传递给另一个函数。
我希望我没有误解这个问题。