The printf
has been borrowed from C and has some limitations. The most common mentioned limitation of printf
is type safety, as it relies on the programmer to correctly match the format string with the arguments. The second limitation that comes again from the varargs environment is that you cannot extend the behavior with user defined types. The printf
knows how to print a set of types, and that's all that you will get out of it. Still, it for the few things that it can be used for, it is faster and simpler to format strings with printf
than with c++ streams.
While most modern compilers, are able to address the type safety limitation and at least provide warnings (the compiler can parse the format string and check the arguments provided in the call), the second limitation cannot be overcome. Even in the first case, there are things that the compiler cannot really help with, as checking for null termination --but then again, the same problem goes with std::cout
if you use it to print the same array.
On the other end, streams (including std::cout
) can be extended to handle user defined types by means of overloaded std::ostream& operator<<( std::ostream&, type const & )
for any given user defined type type
. They are type safe by themselves --if you pass in a type that has no overloaded operator<<
the compiler will complain. They are, on the other hand, more cumbersome to produce formatted output.
So what should you use? In general I prefer using streams, as overloading operator<<
for my own types is simple and they can be used uniformly with all types.