vsprintf() does not print warning when having more arguments then specified in format

79 views Asked by At

I was trying the create an error check while creating logs, with a simple logging mechanism. I observed that it is possible use vfprintf(), that it does not print any warning at compile time, that too many arguments were passed to format (see example below), compared to printf. (I don't expect them to have same behavior, but something similar I still expect). Regarding this issue, even if the number of variadic parameters is known at compile time. It is available any way of checking at compile time? Below, I prepared a code sample, where at compile time the compiler will print a warning regarding the printf, and where the vfprintf() works fine, without any errors. Is maybe the second variadic argument ignored ? I read the man, but I could not find any helpful information.

#include <stdarg.h>
#include <stdio.h>

void check_printf_usage(char *fmt, ...)
{
    va_list ap;
    
    va_start(ap, fmt);
    vfprintf(stdout, fmt, ap);
    va_end(ap);
}

int main()
{
    int x = 1;
    int y = 2;
    printf("test nr.1 %i\n", x, y); // works as expected, prints warning
    check_printf_usage("test nr.2 %i\n", x, y); // does not print any warning

    return 0;
}

Here is the compile output + the program output:

main.c: In function ‘main’:
main.c:21:12: warning: too many arguments for format [-Wformat-extra-args]
   21 |     printf("test nr.1 %i\n", x, y);
      |            ^~~~~~~~~~~~~~~~
test nr.1 1
test nr.2 1
1

There are 1 answers

0
chqrlie On

Argument checking for printf and friends is a very useful extension provided by the compiler (both gcc and clang). You can tell the compiler that your function check_printf_usage expects a variable list of arguments that follows the same rules as printf by tagging the declaration with __attribute__((format(printf, 1, 2))) between the argument list and the ;:

void check_printf_usage(char *fmt, ...) __attribute__((format(printf, 1, 2)));

The first numerical argument, 1, is the 1-based position of the format string argument and the second, 2, is the position of the first argument that corresponds to the format string specifications.