I have a function in my error reporting library with a declaration in the header, for example:
extern void err_logmsg(FILE *fp, int flags, int estat, const char *format, ...) PRINTFLIKE(4,5);
PRINTFLIKE is uppercase, so I can define it as nothing when I don't use GCC. This usage suggests that the first three arguments are not special, but the fourth argument is a format string, such as those used by printf() (indeed, internally it is passed to vfprintf() ) and its corresponding arguments (formatted using a format string) start with the fifth argument.
This means that if I type:
err_logmsg(stdout, ERR_ABORT, 1, "%s: %d\n", errno, strerror(errno));
I will get a compilation error because errno is int and strerror(errno) returns a pointer to a string. I can fix the error by changing the format string or the fifth and sixth arguments. (ERR_ABORT is a set of flags defined in the same header that err_logmsg() declares.)
There are two numbers in the PRINTFLIKE macro, because there can be other arguments between the format string and the first argument used by the format string. For example, an alternative function might be:
extern void err_writer(FILE *fp, const char *format, int flags, int estat, ...) PRINTFLIKE(2,5);
This tells the compiler that the format string is the second argument, but all other arguments that are formatted still appear starting from the fifth argument.
The header file for this code contains the lines:
#ifdef __GNUC__ #define PRINTFLIKE(n,m) __attribute__((format(printf,n,m))) #define NORETURN() __attribute__((noreturn)) #else #define PRINTFLIKE(n,m) #define NORETURN() #endif