'printf' vs. 'cout' in C++
c++, cout, iostream, printf, stdio
Solution
I'm surprised that everyone in this question claims that `std::cout` is way better than `printf`, even if the question just asked for differences. Now, there is a difference - `std::cout` is C++, and `printf` is C (however, you can use it in C++, just like almost anything else from C). Now, I'll be honest here; both `printf` and `std::cout` have their advantages.
Real differences
Extensibility
`std::cout` is extensible. I know that people will say that `printf` is extensible too, but such extension is not mentioned in the C standard (so you would have to use non-standard features - but not even common non-standard feature exists), and such extensions are one letter (so it's easy to conflict with an already-existing format).
Unlike `printf`, `std::cout` depends completely on operator overloading, so there is no issue with custom formats - all you do is define a subroutine taking `std::ostream` as the first argument and your type as second. As such, there are no namespace problems - as long you have a class (which isn't limited to one character), you can have working `std::ostream` overloading for it.
However, I doubt that many people would want to extend `ostream` (to be honest, I rarely saw such extensions, even if they are easy to make). However, it's here if you need it.
Syntax
As it could be easily noticed, both `printf` and `std::cout` use different syntax. `printf` uses standard function syntax using pattern string and variable-length argument lists. Actually, `printf` is a reason why C has them - `printf` formats are too complex to be usable without them. However, `std::cout` uses a different API - the `operator <<` API that returns itself.
Generally, that means the C version will be shorter, but in most cases it won't matter. The difference is noticeable when you print many arguments. If you have to write something like `Error 2: File not found.`, assuming error number, and its description is placeholder, the code would look like this. Both examples work identically (well, sort of, `std::endl` actually flushes the buffer).
printf("Error %d: %s.\n", id, errors[id]);
std::cout << "Error " << id << ": " << errors[id] << "." << std::endl;
While this doesn't appear too crazy (it's just two times longer), things get more crazy when you actually format arguments, instead of just printing them. For example, printing of something like `0x0424` is just crazy. This is caused by `std::cout` mixing state and actual values. I never saw a language where something like `std::setfill` would be a type (other than C++, of course). `printf` clearly separates arguments and actual type. I really would prefer to maintain the `printf` version of it (even if it looks kind of cryptic) compared to `iostream` version of it (as it contains too much noise).
printf("0x%04x\n", 0x424);
std::cout << "0x" << std::hex << std::setfill('0') << std::setw(4) << 0x424 << std::endl;
Translation
This is where the real advantage of `printf` lies. The `printf` format string is well... a string. That makes it really easy to translate, compared to `operator <<` abuse of `iostream`. Assuming that the `gettext()` function translates, and you want to show `Error 2: File not found.`, the code to get translation of the previously shown format string would look like this:
printf(gettext("Error %d: %s.\n"), id, errors[id]);
Now, let's assume that we translate to Fictionish, where the error number is after the description. The translated string would look like `%2$s oru %1$d.\n`. Now, how to do it in C++? Well, I have no idea. I guess you can make fake `iostream` which constructs `printf` that you can pass to `gettext`, or something, for purposes of translation. Of course, `$` is not C standard, but it's so common that it's safe to use in my opinion.
Not having to remember/look-up specific integer type syntax
C has lots of integer types, and so does C++. `std::cout` handles all types for you, while `printf` requires specific syntax depending on an integer type (there are non-integer types, but the only non-integer type you will use in practice with `printf` is `const char *` (C string, can be obtained using `to_c` method of `std::string`)). For instance, to print `size_t`, you need to use `%zu`, while `int64_t` will require using `%"PRId64"`. The tables are available at http://en.cppreference.com/w/cpp/io/c/fprintf and http://en.cppreference.com/w/cpp/types/integer.
You can't print the NUL byte, `\0`
Because `printf` uses C strings as opposed to C++ strings, it cannot print NUL byte without specific tricks. In certain cases it's possible to use `%c` with `'\0'` as an argument, although that's clearly a hack.
Differences nobody cares about
Performance
Update: It turns out that `iostream` is so slow that it's usually slower than your hard drive (if you redirect your program to file). Disabling synchronization with `stdio` may help, if you need to output lots of data. If the performance is a real concern (as opposed to writing several lines to STDOUT), just use `printf`.
Everyone thinks that they care about performance, but nobody bothers to measure it. My answer is that I/O is bottleneck anyway, no matter if you use `printf` or `iostream`. I think that `printf` could be faster from a quick look into assembly (compiled with clang using the `-O3` compiler option). Assuming my error example, `printf` example does way fewer calls than the `cout` example. This is `int main` with `printf`:
main: @ @main
@ BB#0:
push {lr}
ldr r0, .LCPI0_0
ldr r2, .LCPI0_1
mov r1, #2
bl printf
mov r0, #0
pop {lr}
mov pc, lr
.align 2
@ BB#1:
You can easily notice that two strings, and `2` (number) are pushed as `printf` arguments. That's about it; there is nothing else. For comparison, this is `iostream` compiled to assembly. No, there is no inlining; every single `operator <<` call means another call with another set of arguments.
main: @ @main
@ BB#0:
push {r4, r5, lr}
ldr r4, .LCPI0_0
ldr r1, .LCPI0_1
mov r2, #6
mov r3, #0
mov r0, r4
bl _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
mov r0, r4
mov r1, #2
bl _ZNSolsEi
ldr r1, .LCPI0_2
mov r2, #2
mov r3, #0
mov r4, r0
bl _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
ldr r1, .LCPI0_3
mov r0, r4
mov r2, #14
mov r3, #0
bl _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
ldr r1, .LCPI0_4
mov r0, r4
mov r2, #1
mov r3, #0
bl _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
ldr r0, [r4]
sub r0, r0, #24
ldr r0, [r0]
add r0, r0, r4
ldr r5, [r0, #240]
cmp r5, #0
beq .LBB0_5
@ BB#1: @ %_ZSt13__check_facetISt5ctypeIcEERKT_PS3_.exit
ldrb r0, [r5, #28]
cmp r0, #0
beq .LBB0_3
@ BB#2:
ldrb r0, [r5, #39]
b .LBB0_4
.LBB0_3:
mov r0, r5
bl _ZNKSt5ctypeIcE13_M_widen_initEv
ldr r0, [r5]
mov r1, #10
ldr r2, [r0, #24]
mov r0, r5
mov lr, pc
mov pc, r2
.LBB0_4: @ %_ZNKSt5ctypeIcE5widenEc.exit
lsl r0, r0, #24
asr r1, r0, #24
mov r0, r4
bl _ZNSo3putEc
bl _ZNSo5flushEv
mov r0, #0
pop {r4, r5, lr}
mov pc, lr
.LBB0_5:
bl _ZSt16__throw_bad_castv
.align 2
@ BB#6:
However, to be honest, this means nothing, as I/O is the bottleneck anyway. I just wanted to show that `iostream` is not faster because it's "type safe". Most C implementations implement `printf` formats using computed goto, so the `printf` is as fast as it can be, even without compiler being aware of `printf` (not that they aren't - some compilers can optimize `printf` in certain cases - constant string ending with `\n` is usually optimized to `puts`).
Inheritance
I don't know why you would want to inherit `ostream`, but I don't care. It's possible with `FILE` too.
class MyFile : public FILE {}
Type safety
True, variable length argument lists have no safety, but that doesn't matter, as popular C compilers can detect problems with `printf` format string if you enable warnings. In fact, Clang can do that without enabling warnings.
$ cat safety.c
#include <stdio.h>
int main(void) {
printf("String: %s\n", 42);
return 0;
}
$ clang safety.c
safety.c:4:28: warning: format specifies type 'char *' but the argument has type 'int' [-Wformat]
printf("String: %s\n", 42);
~~ ^~
%d
1 warning generated.
$ gcc -Wall safety.c
safety.c: In function ‘main’:
safety.c:4:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf("String: %s\n", 42);
^
Problem
What is the difference between `printf()` and `cout` in C++?