Wednesday, July 6, 2011

pm.c:7355: warning: int format, different type arg (arg 8)

This warning in 9V4 (but not in 9S50) is due to the fact that in Ft Proto.h, we have:

#ifdef GNUC
int FtFormatInternationalMsg (nl_catd catd, int set_number,
                              int message_number, _TCHAR defaultString,
                              _TCHAR destMsgBuf, int sizeDestMsgBuf, ...)
    attribute((format(printf, 4, 7)));

Explanation:

attribute format

This attribute allows assigning printf-like or scanf-like characteristics to the declared function, and this enables the compiler to check the format string against the parameters provided throughout the code. This is exceptionally helpful in tracking down hard-to-find bugs.

There are two flavors:

  • attribute((format(printf,m,n)))
  • attribute((format(scanf,m,n)))

but in practice we use the first one much more often.

The (m) is the number of the “format string” parameter, and (n) is the number of the first variadic parameter. To see some examples:

/* like printf() but to standard error only */
 extern void eprintf(const char *format, ...)
     __attribute__((format(printf, 1, 2)));  /* 1=format 2=params */

 /* printf only if debugging is at the desired level */
 extern void dprintf(int dlevel, const char *format, ...)
     __attribute__((format(printf, 2, 3)));  /* 2=format 3=params */

With the functions so declared, the compiler will examine the argument lists

$ cat test.c
 1  extern void eprintf(const char *format, ...)
 2               __attribute__((format(printf, 1, 2)));
 3
 4  void foo()
 5  {
 6      eprintf("s=%s\n", 5);             /* error on this line */
 7
 8      eprintf("n=%d,%d,%d\n", 1, 2);    /* error on this line */
 9  }
 $ cc -Wall -c test.c
 test.c: In function `foo':
 test.c:6: warning: format argument is not a pointer (arg 2)
 test.c:8: warning: too few arguments for format

Note that the “standard” library functions – printf and the like – are already understood by the compiler by default.