$ printf "hi"
hi$ printf "hi\n"
hi
$ printf "hi\\n"
hi
Why doesn't the last line print hi\n?
This is nothing to do with printf, and everything to do with the argument that you have given to printf.
In a double-quoted string, the shell turns \\ into \.  So the argument that you have given to printf is actually hi\n, which of course printf then performs its own escape sequence processing on.
In a double-quoted string, the escaping done through \ by the shell is specifically limited to affecting the ␊, \, `, $, and " characters.  You will find that \n gets passed to printf as-is.  So the argument that you have given to printf is actually hi\n again.
Be careful about putting escape sequences into the format string for printf.  Only some have defined meanings in the Single Unix Specification.  \n is defined, but \c is actually not, for example.
printf "hi\\\\n" will print the single literal backslash.
                
                printf. The exception would be if you want to have a literal single quote in the format string.
                
                \n is the same as \\n, so \\\n is the same as \\\\n. Honestly, it's better to just use single-quotes to avoid this shell behaviour.
                
                \n gets passed to printf as-is.
                
                ! (or whatever the first character of $histchars is), but in the case of bash, the backslash is not removed. (echo -E "\!foo" still outputs \!foo in bash even though backslash served its purpose at disabling history substitution)
                
                Within double quotes, \\n is an escaped (quoted) backslash followed by a n.  This is given to printf as \n and printf will output a newline.
Within double quotes (still), \n is the string \n. Again, printf receives a \n string and will print a newline.
Within double quotes, backslash is special only when preceding another backslash, a newline, or any of $, ` or ".  "Special" means that it removes the special meaning of the next character.  If a backslash precedes any other character (n for example), then it's just a backslash character.
This is explained in the POSIX standard.
To print \n in a printf format string, use printf '\\n' or printf "\\\\n", or use printf '%s' '\n'
In general, the printf format string should be single quoted and any variable data should be given as additional arguments to be inserted into the format string:
printf 'This is how you write a newline: %s\n' '\n'
Ok, lets add another point of view.
There are two levels of interpretation here at play. One is the shell, the other is the command (in this case printf) interpretation of the arguments received.
Inside double quotes The shell will leave alone most of the sequences backslash-character, this is the common result:
$ printf '%s\n'    "\a \b \c \d ... \z     \$ \` \\ "
\a \b \c \d ... \z     $ ` \
Except with $, `, and \ which, being especial to the shell, get their \ removed.
So, testing both the strings you used (and others), we get:
$ printf '%s\n'     "hi\n"     "hi\\n"    "hi\\\n"    "hi\\\\n"    "hi\\\\\n"
hi\n
hi\n
hi\\n
hi\\n
hi\\\n
The shell converts pairs of \\ to one \. And leaves alone \n as \n.
Now, printf has an special relation to the first argument, it is explicitly set to be the format. In the format argument, some characters are special (to printf), for example: valid sequences that start with a % character and some sequences of backslash-character like:
\\  \a  \b  \f  \n  \r  \t  \v  and the special \ddd
So, the string \n generates a newline but a \\n don't: 
$ printf "    hi\n    hi\\n    hi\\\n   hi\\\\n"; echo
hi
hi
hi\n   hi\n
printf(which is almost surely true),printf "hi\\n"is perfectly valid.printf "hi\\n"being invalid.printfwith a single argument is perfecty valid. The format string can contain other characters and does not need to include any format specifiers. The OP's problem has to do with how the argument is escaped by the shell, not with the wayprintfis being used.