Question

When we use printf then we use format specifiers (such as %c,%p) but when we use cout we don't use them why and what is being done in background because which we are not using them ?

I know they are used in differently in c and c++ but still i want to know how formatting is being done in cout, while it is done in printf through format specifiers.

Was it helpful?

Solution

In C++ the ostream::operator<< is overloaded for different types. You can try and dig through your standard library implementation to see exactly what it looks like, but it will boil down to something that is approximately equivalent to the following:

class ostream
{
public:
   ostream& operator<<( int val );
   ostream& operator<<( float val );
   ostream& operator<<( const char* val );
};

A real implementation will be much more complicated than the above, but that is roughly the idea. The hope was that this implementation would be more efficient than printf because the compiler could more easily inline code when appropriate. Consider the following:

int val = 0;
printf("%d\n", val);
std::cout << val << std::endl;

In the case of the printf a naively compiled program (one compiled by a compiler with no knowledge of format specifiers) would have to do the parsing of "%d\n" at runtime. Contrast that with the std::cout call, in which case the compiler merely needs to figure out which overload to use, and can then inline the code.

That said, there is nothing in the c standard that says a compiler can't parse the format specifiers at compile time if they are available. In practice the performance difference between a c style logging library using format specifiers and c++ ostreams is... nuanced.

OTHER TIPS

Because printf is properly designed and cout has nasty internal state. With printf, the way you want each argument formatted is explicit in the format string; there is no hidden state. With cout, you can also control formatting (things like field width, etc.), but it's a hidden state inside the iostream object. If the previous user of the stream has left it in a non-default state, you'll do the wrong thing unless you explicitly reset the state. You don't even want to think about what happens in multi-threaded usage cases...

Basically the answer is operator overloading. Functions can have the same name as long as they take different parameters. operator<< is the function name you're wondering about. The compiler knows the type of what you're trying to print out, and calls the correct operator<<.

This is why if you create your own object you can't just write std::cout << yourObject; and expect it to work how you'd probably like it to. You have to specify how it should be printed,

ostream& operator<<(ostream& os, const YourObject& rhs) {
  os << rhs.member;
  return os;
}

But, happily, that's already been done for you behind the scenes in the case of something like an int. See: http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt2 for a full list of provided overloads.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top