我创建了一个打印键和值对的函数,其中键是“受信任的编译时文字”字符串,可能包含 printf 说明符。现在我的问题是:根据 c 标准(如 c99),这个函数合法吗?如果没有,我可以做些什么来符合吗?
void pairs(char *message, ...)
{
va_list args;
va_start(args, message);
char *key = va_arg(args, char *);
if (key == NULL) {
va_end(args);
return;
}
while (key != NULL) {
if (key[0] == '%') {
int len = strlen(key);
printf("%s=", &key[len + 1]);
// Copy the current state of the va_list and pass it to vprintf
va_list args2;
va_copy(args2, args);
vprintf(key, args2);
va_end(args2);
// Consume one argument assuming vprintf consumed one
va_arg(args, char *);
} else {
// if no format assume it is a string
fprintf(_log_stream, "%s=\"%s\"", key, va_arg(args, char *));
}
key = va_arg(args, char *);
if (key == NULL)
break;
printf(", ");
}
va_end(args);
}
它应该像这样工作
pairs("This is a beautiful value",
"%d\0hello", 10,
"pass", user_var,
"hello", "bye", NULL);
它实际上正确输出:
hello=10, pass="sus", hello="bye"
所以它可以在我的机器上运行(使用 gcc)。但话又说回来,它合规吗?
// Consume one argument assuming vprintf consumed one
va_arg(args, char *);
因为下一个参数可能不是
char *
。我用参数对
"%f\0hello", 11.0,
对此进行了测试,结果崩溃了。您想要的是关闭args
,将
args2
复制到args
,这样您就可以从上次停下的地方继续,然后关闭args2
。if (key[0] == '%') {
int len = strlen(key);
printf("%s=", &key[len + 1]);
// Copy the current state of the va_list and pass it to vprintf
va_list args2;
va_copy(args2, args);
vprintf(key, args2);
// Copy the current state back to args
va_end(args);
va_copy(args, args2);
va_end(args2);
} else {
...