cout vs printf

I'm relatively new to c and c++. Generally I use the g++ compiler but I haven't really been all that careful about using c code as opposed to c++. The way I see it, it shouldn't matter as long as memory is managed. please correct me if I'm wrong.

Anyway, I don't really like the cout function, I prefer printf because I think it is easier to work with. I've been using printf in my c++ code.
One problem I have run into is that I'm not sure how to represent certain variable types such as an unsigned long. %d doesn't work. Is it possible, or is this one of the reasons why I should stick with cout?
printf("%0.2f", 3.141);

is nicer than

cout << setiosflags<ios::fixed> << setprecision(2) << 3.141;

but

cout << 5 << " + " << 4 << " = " << 9;

is a little bit easier to keep track of than

printf("%u + %u = %u", 5, 4, 9);

in my opinion.

%u is what you're looking for btw.
Last edited on
The big problems with printf are:
- Can't define your own type (iostream can overload new << operators... printf can't overload new % types).
- it's not type aware and therefore is error prone. Examples:
1
2
3
4
5
6
7
8
printf("%f", 5);  // explode
printf("%d", 2.1);  // explode

const char* foo = "I want a 3%discount";
printf(foo); // explode

const std::string bar = "blah blah";
printf("%s", bar) // explode 


The above are all incorrect uses of printf and will cause very strange/bad behavior in a program, and will often not trigger any compiler error. So you won't find out there's a problem until your program starts acting stupid.


The big problems with iostream/cout:
- Operates as a state machine which means it can't be threadsafe.
- Extremely verbose (typically much more to type than the printf alternative)



So there's definitely a tradeoff. I tend to prefer C++ solutions (so I'd prefer iostream in this case) for the increased type safety and expandability.
If std::ios_base::sync_with_stdio(false) has not been invoked:

A standard C stream and the corresponding standard C++ stream use the same buffer; input/output with these (for instance printf() and std::cout << ) can be mixed freely; C++ standard streams are guaranteed by the IS to be as thread-safe as the C standard streams (no data races, but interleaved characters may occur).
printf("%u + %u = %u", a, b , c); is nothing, how about printf("%" PRIu32 " + %"PRIu32 " = %"PRIu32, a, b, c);? C I/O can be terribly verbose.

@OP
how to represent certain variable types such as an unsigned long

printf cannot represent a variable as any type other than its own, exact, type (barring ellipsis conversions, which are the obscure reason why %f is used for both float and double): if you wrote %lu, the type of the corresponding argument must be unsigned long int, or else the behavior is undefined.
Last edited on
C++ standard streams are guaranteed by the IS to be as thread-safe as the C standard streams (no data races, but interleaved characters may occur).


What I mean is... outputting a single statement to an ostream may require multiple steps. Each step individually may be threadsafe, but the act as a whole is not.

1
2
3
4
5
6
7
8
9
void thread1()
{
  cout << setw(4) << setfill('0') << 10;
}

void thread2()
{
  cout << setw(2) << setfill('x') << 1;
}


The problem with this structure is that each << operator is evaluated independently of each other. So there is no guarantee that these threads will print what you'd expect here.

The only way this could work is if cout (or really... all ostream objects) maintain a unique state per thread. And if that's the case, that opens up a whole other set of problems.


Compare this to printf... where everything is channeled through a single function call... which makes it much easier to be threadsafe.
> Each step individually may be threadsafe, but the act as a whole is not.

There will be no race conditions, even if multiple steps are involved (It is threadsafe).



> So there is no guarantee that these threads will print what you'd expect here.

Repeat: but interleaved characters may occur.
Which, AFAIK, is also true for C stdio functions.

Characters generated by fprintf() and printf() are printed as if fputc() had been called.


> Compare this to printf... where everything is channeled through a single function call... which makes it much easier to be threadsafe.

It makes it much more difficult to be threadsafe (dependencies on global objects).

Invoking printf() (or for that matter, any C stdio function on any stream) from one thread and concurrently invoking setlocale() from another thread is not threadsafe, it can lead to race conditions.

The Posix/C++ Binding group suggests that LWG issue 708 be closed as Not-A-Defect. C++ locale objects are already adequate for thread-safe locales; setlocale() is thread-unsafe.
- http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1371.htm
Topic archived. No new replies allowed.