这是使用 va_copy 未定义的行为吗?

问题描述 投票:0回答:1

我创建了一个打印键和值对的函数,其中键是“受信任的编译时文字”字符串,可能包含 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)。但话又说回来,它合规吗?

    

c undefined-behavior variadic-functions c99 ansi-c
1个回答
0
投票

// 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 {
...

© www.soinside.com 2019 - 2024. All rights reserved.