__printflike__ modifier
what is "__printflike__ modifier" exactly? what does thi开发者_开发技巧s term mean?
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.
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__ */
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?
精彩评论