如果格式字符串没有 % 引用,vsprintf() 是否保证不访问 va_list?

Is vsprintf() guaranteed not to access va_list if format string makes no % references?

如果传递给 vsprintf()(及其变体)的格式字符串不包含 %-references,是否保证 va_list 参数未被访问?

换句话说,就是:

#include <stdarg.h>
#include <stdio.h>
int main ( void ) {
    char    str[16];
    va_list ap;         /* never initialized */

    (void)vsnprintf(str, sizeof(str), "", ap);
    return 0;
}

符合标准的程序?或者那里有未定义的行为?

上面的例子显然很愚蠢,但想象一下一个可以被可变参数函数和固定参数函数调用的函数,粗略地简化成类似这样的东西:

void somefuncVA ( const char * fmt, va_list ap ) {
    char    str[16];
    int     n;

    n = vsnprintf(str, sizeof(str), fmt, ap);
    /* potentially do something with str */
}

void vfoo ( const char * fmt, ... ) {
    va_list ap;

    va_start(fmt, ap);
    somefuncVA(fmt, ap);
}

void foo ( void ) {
    va_list ap;     /* no way to initialize this */

    somefuncVA("", ap);
}

如果您没有将可变参数传递给您的函数 - 您的函数未将 ... 定义为最后一个参数 - 根本不需要使用 va_listva_start() 在该函数中。如果您想传递一组空的可变参数,只需直接调用不带任何可变参数的 varargs 函数 - 例如,printf("\n");.

例如,而不是

void foo ( void ) {
    va_list ap;     /* no way to initialize this */

    somefuncVA("", ap);
}

你可以写

void foo ( void ) {
    vfoo("");
}
int vsprintf(char * restrict s, const char * restrict format, va_list arg);

If the format string passed to vsprintf() ... contains no %-references, is it guaranteed that the va_list argument is not accessed.

没有

The vsprintf function is equivalent to sprintf, with the variable argument list replaced by arg, which shall have been initialized by the va_start macro .....
C11dr §7.21.6.13

由于下面的代码不符合规范,结果是未定义的行为 (UB)。没有保证。

va_list ap;
//                                    vv-- ap not initialized
(void)vsnprintf(str, sizeof(str), "", ap);

Is vsprintf() guaranteed not to access va_list if format string makes no % references?

通过正确传递 va_list argvsprintf() 的行为类似于 sprintf()。像下面这样的代码就可以了。允许传递额外的参数。通过 vsprintf(),它们(额外的参数)不会被访问,但是 va_list arg 可以被访问。

sprintf(buf, "format without percent", 1.2345, 456)`