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?

Community
  • 1
  • 1
  • 7
    If you're writing C++ code then you should in general prefer C++ idioms and libraries. – Paul R Jan 24 '11 at 12:15
  • 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. – Harry Joy Jan 24 '11 at 12:17
  • 1
    @Paul R. Thanks for your reply. So, isn't "printf()" then considered a C++ idiom? –  Jan 24 '11 at 12:17
  • @Harry Joy. Thanks for your reply. I'm using C++. –  Jan 24 '11 at 12:18
  • 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 SFINAE – CashCow Jan 24 '11 at 12:26
  • 3
    duplicate of http://stackoverflow.com/questions/2017489/should-i-use-printf-in-my-c-code – mingos Jan 24 '11 at 12:55

7 Answers7

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;
dandan78
  • 13,328
  • 13
  • 64
  • 78
  • 5
    +1, you have stated one advantage of printf so looks like a valid answer to me. – CashCow Jan 24 '11 at 12:24
  • 7
    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. – Zac Howland Jan 24 '11 at 12:34
  • 3
    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. – dandan78 Jan 24 '11 at 12:37
  • 1
    -1: Proper `cout` usage is: `cout << person << '\n'`. Common misconception. – Sebastian Mach Feb 09 '12 at 13:10
  • How so? endl = end line!? – paulm Jan 22 '13 at 08:59
  • 2
    `endl` should only be used when you want to flush the stream, too. – Cerran Feb 20 '14 at 19:15
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.

Zac Howland
  • 15,777
  • 1
  • 26
  • 42
  • 1
    @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. –  Jan 24 '11 at 12:25
  • I don't think this is very relevant when printing a string literal. – moinudin Jan 24 '11 at 12:26
  • 3
    @ 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. – Ward Muylaert Jan 24 '11 at 12:28
  • @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. – Zac Howland Jan 24 '11 at 12:31
  • @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. –  Jan 24 '11 at 12:31
  • 3
    @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. – Zac Howland Jan 24 '11 at 12:36
  • 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. – CashCow Jan 24 '11 at 12:36
  • @CashCow: Assuming you're using `std::string` or `std::vector` 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` instead, `std::copy(v.begin(), v.end(), std::ostream_iterator(std::cout, ""));` doesn't have the problem either. – Zac Howland Jan 24 '11 at 12:40
  • 3
    @Zac, I think that what @CashCow 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. – David Rodríguez - dribeas Jan 24 '11 at 13:03
  • @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. – Zac Howland Jan 24 '11 at 13:06
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.

vy32
  • 28,461
  • 37
  • 122
  • 246
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.

CashCow
  • 30,981
  • 5
  • 61
  • 92
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.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
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.

moinudin
  • 134,091
  • 45
  • 190
  • 216
  • 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. –  Jan 24 '11 at 12:22
  • @aali 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. – moinudin Jan 24 '11 at 12:28
  • With g++4.x, in the testcases I committed, ostreams are as fast as printfs, if you `sync_with_stdio(false)`. – Sebastian Mach Feb 09 '12 at 13:12
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.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • Thanks for your reply. I saw that "printf()" enables formatting, does "cout" provide that too? –  Jan 24 '11 at 12:19
  • 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. –  Jan 24 '11 at 12:20
  • @aali: cout also provides output formatting. – Harry Joy Jan 24 '11 at 12:22
  • Do you have a reference for printf being many times faster? – CB Bailey Jan 24 '11 at 12:24
  • @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`. – Puppy Jan 24 '11 at 12:31
  • @DeadMG: `printf` is only faster if you sync with stdio, which is enabled by default. – Sebastian Mach Aug 28 '13 at 07:31