printf("foo: ");
vs
fputs("foo: ", stdout);
As mentioned in the title, the string is not formatted and does not end in a new line (so no puts). I am not sure about overheads and optimizations, so what is the rule of thumb is this case?
EDIT: Is it normal practice to use printf with non-formatted strings?
What is the right way
Both ways are "right", both will work the same and fine.
Consider rules of optimization. Don't optimize, if you don't have to. printf("foo: ");
is completely fine, readable, understandable, everyone knows what it means. Keep it. printf("foo :");
is great.
If you really want to optimize, and you really care about speed, you could call fwrite
with statically calculated values:
fwrite("foo: ", 1, sizeof("foo: ") - 1, stdout);
But I doubt that optimization is worth anything. If you would really care about speed, you would call OS specific functions anyway, like on Linux we have write
or splice
or tee
or vmsplice
or copy_file_range
or sendfile
.
if it is normal practice to use printf for non-formatted strings
Let's take some big project and check. Analyzing gcc source code, there are that many lines matching fputs with a literal string:
$ rg -g '*.[ch]' 'fputs\s*\(\s*"[^"]*"' gcc/ | wc -l
263
$ rg -g '*.[ch]' 'fputs\s*\(\s*"[^"]*"' gcc/ | head
gcc/defaults.h: fputs (":\n", (FILE)); \
gcc/defaults.h: fputs (":\n", (FILE)); \
gcc/defaults.h: fputs (", ", STREAM); \
gcc/defaults.h: fputs (", .-", STREAM); \
gcc/config/csky/csky.h: fputs ("\t.comm\t", STREAM); \
gcc/config/csky/csky.h: fputs ("\t.bss\t", (STREAM)); \
gcc/config/xtensa/xtensa.h: fputs ("@pcrel", FILE); \
gcc/config/c6x/c6x.h: fputs ("\t.long ", FILE); \
gcc/config/visium/visium.h: do { assemble_name (STREAM, NAME); fputs (":\n", STREAM); } while (0)
gcc/config/visium/visium.h:( fputs ("\n\t.comm ", (STREAM)),
And that many lines matching printf with literal string and no arguments:
$ rg -g '*.[ch]' 'printf\s*\(\s*"[^"]*"\);' gcc/ | wc -l
1792
There are that many lines with printf
that have no newlines in formatting string:
$ rg -g '*.[ch]' 'printf\s*\(\s*"[^"]*"\);' gcc/ | grep -v '"[^"]*\\n[^"]*"' | wc -l
470
$ rg -g '*.[ch]' 'printf\s*\(\s*"[^"]*"\);' | grep -v '"[^"]*\\n[^"]*"' | head
zlib/contrib/minizip/miniunz.c: printf(" ");
libdecnumber/decNumber.c: if (decNumberIsInfinite(dn)) printf("Infinity");
libdecnumber/decNumber.c: if (dn->bits&DECSNAN) printf("sNaN"); /* signalling NaN */
libdecnumber/decNumber.c: else printf("NaN");
libdecnumber/decNumber.c: printf(" ");
libdecnumber/decNumber.c: printf(":");
libdecnumber/decCommon.c: if ((num->lsd-ub)%3==0 && ub!=num->lsd) printf(" "); /* 4-space */
libdecnumber/decBasic.c: printf("----- div=");
libdecnumber/decBasic.c: printf("DivQuo:");
libdecnumber/decBasic.c: printf("CoeffbL:");
These numbers look high enough, I would say any is "right". Looking at it, there are even more printf("literal")
than fputs("literal", anything)
.