In C, particularly due to the lack of dynamic strings, it's common to pass format strings around together with a variable set of arguments. A prototype like this is very common:

void my_printf(const char*, ...);

For the standard printf and similar functions, some compilers will ensure that the variable list of arguments matches the positional parameters in the format string and, if they don't match, raise a warning.  This is, however, just a warning "hardcoded" to match these functions, as the compiler can't know how the variable arguments of our custom my_printf function relate to the first argument.

Or can it?

I was made aware of a nice GCC attribute that allows developers to tag printf-like functions in a manner that allows the compiler to perform the same validation of variable arguments and format strings.  This is in the form of a GCC __attribute__ that also happens to work with CLang.  Let's see an example to illustrate how this works:

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

static void my_printf(const char*, ...)
    __attribute__((format(printf, 1, 2)));

static void
my_printf(const char* format, ...)
    va_list ap;

    printf("Custom printf: ");
    va_start(ap, format);
    vprintf(format, ap);

    my_printf("this is valid %dn", 3);
    my_printf("but this is not %fn", 3);

If we compile the code above:

$ clang example.c
example.c:22:33: warning: conversion specifies type 'double' but
the argument has type 'int' [-Wformat]
    my_printf("but this is not %fn", 3);
                               ~^     ~
1 warning generated.

Very useful.  This function attribute has been applied to many functions in the NetBSD tree and many bugs have been spotted thanks to it.

Instead of me explaining how the format attribute works, I'll refer you to the official documentation. The attribute recognizes several format styles and takes different arguments depending on them, so it is a bit tricky to explain. Plus, if you look at the extensive list of attributes, you may find some useful stuff ;-)

Happy debugging!

Subscribe via RSS · Go to posts index

   Delivered by FeedBurner

Comments from the original Blogger-hosted post: