如果您想编写一个以va_list 作为参数的函数,就像vprintf 所做的那样,那么您只需这样做。您可以以正常方式从va_list 和va_arg 中提取参数。
不要在va_list 上拨打va_start 或va_end:这是呼叫者的责任。由于无法正常重启va_list,如果需要多次扫描,则需要va_copy。
这是一个简单的示例,仅用于说明(即它并不是最好的实现)。
这两个函数只是使用提供的分隔符字符串连接一堆字符串。第一个是“v”版本(如vsprintf),它实现了逻辑。第二个是 varargs 版本,它将 va_list 打包并传递给实现。
内部函数两次遍历参数;第一次添加字符串的大小。两个函数都返回一个新的 malloc 字符串,调用者需要释放该字符串。
参数列表必须以NULL 结束。
char* vjoin(const char* delim, va_list ap) {
va_list aq;
va_copy(aq, ap);
size_t dlen = strlen(delim);
/* First pass. Use the copied va_list */
size_t needed = 1; /* NUL terminator */
const char* s = va_arg(aq, const char*);
if (s) {
needed += strlen(s);
while ((s = va_arg(aq, const char*)))
needed += dlen + strlen(s);
}
va_end(aq);
/* Second pass. Use the original va_list */
char* rv = malloc(needed);
size_t offset = 0;
*rv = 0;
s = va_arg(ap, const char*);
if (s) {
strcpy(rv, s);
offset = strlen(s);
while ((s = va_arg(ap, const char*))) {
strcpy(rv + offset, delim);
strcpy(rv + offset + dlen, s);
offset += dlen + strlen(s);
}
}
return rv;
}
char* join(const char* delim, ...) {
va_list ap;
va_start(ap, delim);
char* rv = vjoin(delim, ap);
va_end(ap);
return rv;
}