printf vs. std::cout [duplicate]
Asked Answered
U

7

17

Possible Duplicate:
Should I use printf in my C++ code?

If I just want to print a string on screen, I can do that using those two ways:

printf("abc");

std::cout << "abc" << std::endl;

The case is, and in the examples shown above, is there an advantage of using printf over std::cout, or, vice versa?

Upstairs answered 24/1, 2011 at 12:13 Comment(6)
If you're writing C++ code then you should in general prefer C++ idioms and libraries.Interpellant
It depends in which language are you writing your program either C or C++. This both methods are of different language so you can't compare it directly.Polyhymnia
@Paul R. Thanks for your reply. So, isn't "printf()" then considered a C++ idiom?Upstairs
@Harry Joy. Thanks for your reply. I'm using C++.Upstairs
It's a free function and C++ supports free functions and there are free functions in the standard library. The non-C++ idiom perhaps is the elipses (...) which are usually only used in C++ as a "cheat" for SFINAEKendalkendall
duplicate of #2017989Latonialatoniah
D
37

While cout is the proper C++ way, I believe that some people and companies (including Google) continue to use printf in C++ code because it is much easier to do formatted output with printf than with cout.

Here's an interesting example that I found here.

Compare:

printf( "%-20s %-20s %5s\n" , "Name" , "Surname" , "Id" );

and

cout << setw( -20 ) << "Name" << setw( 20 ) << "Surname"  << setw( 5 ) << "Id" << endl;
Divinadivination answered 24/1, 2011 at 12:18 Comment(6)
+1, you have stated one advantage of printf so looks like a valid answer to me.Kendalkendall
An example showing that a smaller line of code does not always mean more readable. The std::cout version explicitly states what it is doing every step of the way. printf has a cryptic formatting string.Juvenescent
That is true, but once you get used to it, it could be argued that printf is the easier to use of the two. Personally, I've always found stream formatting to be very clunky.Divinadivination
-1: Proper cout usage is: cout << person << '\n'. Common misconception.Cartilage
How so? endl = end line!?Weatherboard
endl should only be used when you want to flush the stream, too.Bott
J
19

printf and its associated friends are C functions. They work in C++, but do not have the type safety of C++ std::ostreams. Problems can arise in programs that use printf functions to format output based on user input (or even input from a file). For example:

int main()
{
    char[] a = {'1', '2', '3', '4'}; // a string that isn't 0-terminated
    int i = 50;
    printf("%s", a); // will continue printing characters until a 0 is found in memory
    printf("%s", i); // will attempt to print a string, but this is actually an integer
}

C++ has much stronger type safety (and a std::string class) to help prevent problems like these.

Juvenescent answered 24/1, 2011 at 12:22 Comment(10)
@Zac Howland. Thanks for your reply. Why isn't that string you declare above 0-terminated? Aren't the strings always 0-terminated? And, what do you mean by "type safety"? Thanks.Upstairs
I don't think this is very relevant when printing a string literal.Ritter
@ aali He defines a character array, those just happen to be able to be interpreted as strings in C, it will not automatically add a zero-byte to the end of an array.Magnetochemistry
@aali: I defined the character array that way to show how the problem is created. That array could just as easily come from a data file that had been corrupted and would cause your program to crash (in fact, this type of bug use to be exploited to get a root-terminal on Nix systems many moons ago). The examples are just a couple of the pitfalls of using printf and family.Juvenescent
@Ward Muylaert. When we declare the string as it is declared here in C++, don't we get \0 added automatically to indicate the end of the sequence? Or, when do we get \0? Thanks.Upstairs
@aali: No, you won't get a terminator automatically added. If I had declared it as char* a = "1234"; there would be one, but the problem I was demonstrating comes in when you do not have a terminator.Juvenescent
yes but you would have the same issue with cout if you tried to output a because it is also interpreted as char* and will try to print until it reaches a '\0' byte so read into undefined territory... The second case there is valid though. Presumably your comment on std::string case 1 will not occur.Kendalkendall
@CashCow: Assuming you're using std::string or std::vector<char> when using C++, no, you won't have that problem when doing the output properly. Assume the array was read in from a file, std::string will always be terminated. If you use a std::vector<char> instead, std::copy(v.begin(), v.end(), std::ostream_iterator<char>(std::cout, "")); doesn't have the problem either.Juvenescent
@Zac, I think that what @Kendalkendall is trying to say is that in that particular case it is exactly the same in both cases. If you limit yourself to std::string and not const char*, then you will not have problems with cout, but you will not have problems with printf either: printf( "%s\n", st.c_str() );. I do agree with your answer, but the type safety issues are diluting with time... gcc will verify the type correctness by parsing the format string at the place of call, providing a compiler warning. Not required by the standard, and yet it's there.Scholarship
@David: True, but I was going more with the idea of using C++-idioms when writing C++, and C-idioms when writing C. Obviously, if you use C++ incorrectly, you can still have problems. However, the primary point with the example was that you can use C correctly and have this problem arise, whereas you cannot if you use C++ correctly.Juvenescent
H
3

I struggle with this very question myself. printf is in general easier to use for formatted printing, but the iostreams facility in C++ has the big advantage that you can create custom formatters for objects. I end up using both of them in my code as necessary.

The problem with using both and intermixing them is that the output buffers used by printf and cout are not the same, so unless you run unbuffered or explicitly flush output you can end up with corrupted output.

My main objection to C++ is that there is no fast output formatting facility similar to printf, so there is no way to easily control output for integer, hex, and floating point formatting.

Java had this same problem; the language ended up getting printf.

Wikipedia has a good discussion of this issue at http://en.wikipedia.org/wiki/Printf#C.2B.2B_alternatives_to_sprintf_for_numeric_conversion.

Heerlen answered 24/1, 2011 at 12:24 Comment(0)
K
2

Actually for your particular example, you should have asked which is preferable, puts or cout. printf prints formatted text but you are just outputting plain text to the console.

For general use, streams (iostream, of which cout is a part) are more extensible (you can print your own types with them), and are more generic in that you can generate functions to print to any type of stream, not just the console (or redirected output). You can create generic stream behaviour with printf too using fprintf which take a FILE* as a FILE* is often not a real file, but this is more tricky.

Streams are "typesafe" in that you overload with the type you are printing. printf is not typesafe with its use of ellipses so you could get undefined results if you put the wrong parameter types in that do not match the format string, but the compiler will not complain. You may even get a seg-fault / undefined behaviour (but you could with cout if used incorrectly) if you miss a parameter or pass in a bad one (eg a number for %s and it treats it as a pointer anyway).

printf does have some advantages though: you can template a format string then reuse that format string for different data, even if that data is not in a struct, and using formatting manipulations for one variable does not "stick" that format for further use because you specify the format for each variable. printf is also known to be threadsafe whereas cout actually is not.

boost has combined the advantages of each with their boost::format library.

Kendalkendall answered 24/1, 2011 at 12:23 Comment(2)
+1 for mentioning boost::formatCellophane
+1 "you should have asked which is preferable, puts or cout". i am googling to try find who calls who internally , puts() has a cout call in it?Concelebrate
P
2

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.

Pique answered 24/1, 2011 at 12:59 Comment(0)
R
1

Those two examples do different things. The latter will add a newline character and flush output (result of std::endl). std::cout is also slower. Other than that, printf and std::cout achieve the same thing and you can choose whichever you prefer. As a matter of preference, I'd use std::cout in C++ code. It's more readable and safer.

See this article if you need to format output using std::cout.

Ritter answered 24/1, 2011 at 12:17 Comment(3)
Thanks for your reply. Why is "std::cout" as you mention is slower? What is meant by "slower" here? In terms of what for example? Thanks.Upstairs
@Upstairs It's slower for the reasons other answers go in detail explaining: it does more stuff. It's very dependant on your compiler, but I've seen older versions of GCC be more than 10x slower in all cases.Ritter
With g++4.x, in the testcases I committed, ostreams are as fast as printfs, if you sync_with_stdio(false).Cartilage
L
0

In general, you should prefer cout because it's much type-safer and more generic. printf isn't type-safe, nor is it generic at all. The only reason you might favour printf is speed- from memory, printf is many times faster than cout.

Libel answered 24/1, 2011 at 12:18 Comment(6)
Thanks for your reply. I saw that "printf()" enables formatting, does "cout" provide that too?Upstairs
What do you mean when you say: "printf isn't type-safe, nor is it generic at all. The only reason you might favour printf is speed- from memory, printf is many times faster than cout."? Can you clarif on that a bit. Thanks.Upstairs
@aali: cout also provides output formatting.Polyhymnia
Do you have a reference for printf being many times faster?Plovdiv
@aali: Your compiler will accept blatant errors with printf, like printf("%s", int());. In addition, many custom types are overloaded to work with iostreams, but you can never printf a custom type. cout provides formatting too. @Charles: Not personally. I know that iostream has a reputation for being very slow, and that when I tested it, it was extremely slow compared to printf.Libel
@DeadMG: printf is only faster if you sync with stdio, which is enabled by default.Cartilage

© 2022 - 2024 — McMap. All rights reserved.