But "Hello world\n" is a format string. The format strings with no % chars in them are the best type of format string! They're nearly impossible to get wrong!
Given how many tutorials leave best practices out on how to do proper error handling, strings and arrays in C, doing analysis as part of the build, I would say golfing most of the time.
That’s not the point of hello world. It’s not to be as small a valid program as possible. It’s to be a small program that also exercises the needed functionality for using the tool usefully. All of the exercises following that hello world need formatted text, so introducing puts would just add confusion and wouldn’t verify that you have a working printf.
Useless bit of compiler optimizations trivia: the "this printf() is equivalent to puts()" optimization seems to work by looking for the '%' in the format string, not by counting whether there is only one argument to printf(), e.g. if you add 42 as a second argument to the printf() — which is absolutely legal and required by the standard to Work as Intended™ — the resulting binary still uses puts().
> puts() writes the string s and a trailing newline to stdout.
int main() { puts("Hello World!"); }