Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__printflike__ modifier

Tags:

c

printf

modifier

what is "__printflike__ modifier" exactly? what does this term mean?

like image 670
hari Avatar asked Apr 28 '11 21:04

hari


3 Answers

At a guess it tells the compiler you're using that a function takes arguments in the form [anything, ] format, ... where the format, ... part look like the arguments to printf. The __printflike__ attribute lets the compiler test the types in the argument list against the string format. This comes up when you write a function like log(format, ...) and use vsprintf to subordinate the formatting work to the usual standard library functions before sending the string to some special log interface.

If you are using GCC then it is probably a #define in your project something like:

#define __printflike__ __attribute__((format(printf, 1, 2)))

Where 1, 2 means that format, ... appear in positions 1 and 2.

like image 117
Ben Jackson Avatar answered Sep 18 '22 10:09

Ben Jackson


I have a function in my error reporting library with the declaration in the header like:

extern void err_logmsg(FILE *fp, int flags, int estat, const char *format, ...)
                       PRINTFLIKE(4,5);

The PRINTFLIKE is in upper-case so that I can define it as nothing when I'm not using GCC. This use says that the first three arguments are nothing special, but the fourth argument is a format string like the ones used by printf() (indeed, internally, it gets passed to vfprintf()), and the arguments corresponding to it (formatted using the 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 an 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 declares err_logmsg().)

There are two numbers in the PRINTFLIKE macro because there could be other arguments between the format string and the first of the arguments used by the format string. For example, an alternative function could 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 that the corresponding arguments that get formatted still appear starting at 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) /* If only */
#define NORETURN()      /* If only */
#endif /* __GNUC__ */
like image 29
Jonathan Leffler Avatar answered Sep 21 '22 10:09

Jonathan Leffler


Probably tells the compiler that the corresponding function has printf-like semantics.

This can enable the compiler to issue warnings at compile-time when the modifiers in the format string do not correspond to the type or the count of the passed arguments.

There is no other way that the compiler can have the knowledge to tell you that %u isn't the right formatting for an int when calling printf, sprintf, fprintf, etc.

I asked the reverse question a few months ago: Are printf/sprintf compiler warnings a conceptual break?

like image 31
Blagovest Buyukliev Avatar answered Sep 22 '22 10:09

Blagovest Buyukliev