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

时间:2018-07-17 14:23:43

标签: c printf variadic-functions

如果传递给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);
}

2 个答案:

答案 0 :(得分:3)

如果您没有将varargs传递给函数-您的函数未使用...作为最后一个参数进行定义-则根本不需要使用va_list或{{1 }}。如果您要传递一组空的变量参数,只需直接调用varargs函数而无需任何变量参数-例如va_start()

例如,代替

printf("\n");

你可以写

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

    somefuncVA("", ap);
}

答案 1 :(得分:3)

int vsprintf(char * restrict s, const char * restrict format, va_list arg);
  

如果传递给vsprintf() ...的格式字符串不包含%-references,则可以确保不会访问va_list参数。

否。

  

vsprintf函数等效于sprintf,带有可变参数列表   被arg宏替换的va_start,该宏已被va_list ap; // vv-- ap not initialized (void)vsnprintf(str, sizeof(str), "", ap); 宏.....
  C11dr§7.21.6.13

由于以下代码不符合规范,因此结果为未定义行为(UB)。没有保证。 @Eugene Sh.

vsprintf()

  

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

通过正确传递的vsprintf()sprintf()的行为类似于vsprintf()。如下代码是可以的。允许传递额外的参数。通过va_list arg,它们(额外的参数)不会被访问,但sprintf(buf, "format without percent", 1.2345, 456)` 可能会被访问​​。

tr