At least for printf, there's normally a way to tell the compiler that it's a printf style interface and get something approaching typesafety back. On gcc this is
extern int
my_printf (void *my_object, const char *my_format, ...)
__attribute__ ((format (printf, 2, 3)));
(Now I like rust's solution better, a sane macro system so this interface doesn't have to be special cased by the compiler to be safe).