I know it doesn't directly answer your question but you could presumably avoid the warning by changing your code to
printf("%s", hi);
In case you have:
void f(char * s) { printf(s); }
you can modify it as:
void f(char * s) { printf("%s", s); }
to get rid of the warning.
EDIT: An easy, slightly limited, probably nasty way of dealing with your new issue would be
char buf[1024];
snprintf(buf, sizeof(buf), "%s %s", "bloody", "warning");
fprintf(stderr, "%s", buf);
It may be possible to generalise this to something like the following (untested!)
my_printf(const char* fmt, ...)
{
va_list ap;
char buf[1024];
vsnprintf(buf, sizeof(buf), fmt, ap);
fprintf(stderr, "%s", buf);
}