What is the difference between printf() and puts() in C?
Solution 1
puts
is simpler than printf
but be aware that the former automatically appends a newline. If that's not what you want, you can fputs
your string to stdout or use printf
.
Solution 2
(This is pointed out in a comment by Zan Lynx, but I think it deserves an answer - given that the accepted answer doesn't mention it).
The essential difference between puts(mystr);
and printf(mystr);
is that in the latter the argument is interpreted as a formatting string. The result will be often the same (except for the added newline) if the string doesn't contain any control characters (%
) but if you cannot rely on that (if mystr
is a variable instead of a literal), you should not use it.
So, it's generally dangerous - and conceptually wrong - to pass a dynamic string as single argument of printf
:
char * myMessage;
// ... myMessage gets assigned at runtime, unpredictable content
printf(myMessage); // <--- WRONG! (what if myMessage contains a '%' char?)
puts(myMessage); // ok
printf("%s\n",myMessage); // ok, equivalent to the previous, perhaps less efficient
The same applies to fputs
vs fprintf
(but fputs
doesn't add the newline).
Solution 3
Besides formatting, puts
returns a nonnegative integer if successful or EOF
if unsuccessful; while printf
returns the number of characters printed (not including the trailing null).
Solution 4
In simple cases, the compiler converts calls to printf()
to calls to puts()
.
For example, the following code will be compiled to the assembly code I show next.
#include <stdio.h>
main() {
printf("Hello world!");
return 0;
}
push rbp
mov rbp,rsp
mov edi,str.Helloworld!
call dword imp.puts
mov eax,0x0
pop rbp
ret
In this example, I used GCC version 4.7.2 and compiled the source with gcc -o hello hello.c
.
Solution 5
In my experience, printf()
hauls in more code than puts()
regardless of the format string.
If I don't need the formatting, I don't use printf
. However, fwrite
to stdout
works a lot faster than puts
.
static const char my_text[] = "Using fwrite.\n";
fwrite(my_text, 1, sizeof(my_text) - sizeof('\0'), stdout);
Note: per comments, '\0' is an integer constant. The correct expression should be sizeof(char)
as indicated by the comments.
Related videos on Youtube
user3167101
I like to make stuff. Check out my blog. You can email me at alex at my domain. My dotfiles, if you're curious :)
Updated on June 26, 2020Comments
-
user3167101 almost 4 years
I know you can print with
printf()
andputs()
. I can also see thatprintf()
allows you to interpolate variables and do formatting.Is
puts()
merely a primitive version ofprintf()
. Should it be used for every possibleprintf()
without string interpolation?-
Anthony Forloney about 14 years
-
Zan Lynx over 11 yearsJust a note on using printf instead of puts: never, ever do a
printf(variable)
to print a string. Useputs(variable)
orprintf("%s', variable)
. There's a security risk in using a variable format string: if the variable can be written by an attacker they can attack the program by using format strings.
-
-
Antony Hatchkins about 11 years"fwrite to stdout works a lot faster than puts." - What could possibly be the reason?
-
zubergu over 10 yearsAnd what about new line that puts places in stdout?
-
Wiz over 10 years@AntonyHatchkins It's typically not "a lot" faster. puts(), however, does have to perform an strlen() call every time on your string whereas if the size is known with fwrite() it can be avoided. That's pretty much the only real contributer to a performance difference.
-
franklin over 9 yearsIn what way would using
printf()
be less efficient? At run time? At compile time? -
leonbloy over 9 years@franklin at runtime, because
printf
needs to parse the format string. However, this should normally be irrelevant. Further, a clever compiler could optimize this, and replace theprintf
with call toputs
-
Rafael Almeida over 9 yearsIt should have been
printf("Hello world!\n");
gcc indeed translates that to puts. Since it's an old message, I will edit it myself. -
Koray Tugay about 9 yearsHow did you read the assembly code after compiling the C code?
-
Bradley Garagan almost 9 yearsThis answer is incorrect.
'\0'
has typeint
, so on most systems this will printUsing fwrit
. If you want to print 1 less byte, just use 1.sizeof (char)
, which is likely what you intended here, is guaranteed to be 1. -
Erutan409 over 8 yearsI think it's also important to mention the additional arguments printf take for adding additional variables into the outputted string.
-
schaiba about 8 years@KorayTugay : the
-save-temps
option for gcc does that -
Ivan Kaloyanov over 4 yearsYou could also use a tool like gdb to disassemble a binary.
-
Nico Haase almost 4 yearsPlease add some explanation to your answer such that others can learn from it - do you have reliable sources for that claim? Or some reasons to explain this difference?
-
Lou about 3 yearsWhen I've tested this, puts returns the number of characters in the string including the terminating character, whereas printf returns the number of characters printed without the terminating character. Which is technically consistent with your definition, as the former is a non-negative integer, but I'm not sure whether that's what you meant to say.
-
diverger over 2 years@lou, are you sure the extra including come from the null terminator but not the '\n'?
-
Tom Kuschel about 2 yearsI do not believe that puts() takes more time than printf(). Note that puts automatically appends a newline.
-
Alex almost 2 yearsAlso $ objdump -d printf.exe -M intel
-
Alex almost 2 yearsBy the way in gcc 7.5.0 assembly looks like = call printf@PLT