Two young Moose - 2010 Algonquin Park

Cout vs Printf

Is the Dinosaur Still King?

I have used and abused the printf function since the 80’s.  Yes, the NINETEEN 80’s.  My first C compiler was Power C on a Commodore C64.  By the time I picked up C, I had learned BASIC and Assembly Language (a mnemonic machine language).  You can imagine the smile on my face when I read the brochure. Basic and Assembly were notoriously difficult to print decimal places, but C made it easy. Not only can I print the correct number of places after the decimal, but have it round for me and space it all out.  I was SOLD.  

Since then, I have found a version of my beloved printf function in the next generation of C, C++.  Even C# has a String.Format function that looks a lot like the printf function.

C++ introduced a lot of new concepts and capabilities.  It introduced a whole new paradigm of programming – the Class.  Object Oriented Programming, OOP.  But, it also introduced a new guy on the block, cout.  That’s SEE-OUT.

cout is simple to use in C++:

cout << "Hello foo!" << endl;

whereas C and C++ could use printf:

printf("Hello foo!\n");

Lets Print Some Floating Point Numbers

printf Version:

				
					float F1 = 0.36789;

printf("%7.2f\n", F1);
>>   0.37
				
			

cout Version:

				
					float F1 = 0.36789;

	std::cout << std::setfill(' ') << std::setw(7) << std::fixed << std::setprecision(2) << F1 << endl;
>>   0.37
				
			

The verdict?  printf wins hands down.  For those of you who rely on AutoComplete, you’ll appreciate the cout version since you can literally CTRL-SPACE your way to an end product.  But, you can’t deny the printf version is a whole lot simpler and requires WAY less typing.  

But… is printf FASTER than cout?

Comparing Speed

I wrote a quick program, shown below to test the speed of each method.  Could it be that cout uses more resources?  Is printf “closer” to the hardware?  Let’s take a look at the numbers and see if your project could see a speed boost.

Printing 20,000 Integers

				
					using namespace std;
#include <stdio.h>
#include <iostream>
#include <iomanip>
#include <chrono>

int main()
{
	int MaxIterations = 20000;

	auto Start1 = std::chrono::high_resolution_clock::now();

	for (int x = 0; x < MaxIterations; x++)
		printf("%6d\r",x);					// print XXXX<CR>

	auto Finish1 = std::chrono::high_resolution_clock::now();
	std::cout << endl << MaxIterations << " Iterations with PRINTF took "  << std::chrono::duration_cast<std::chrono::milliseconds>(Finish1 - Start1).count() << "mS\n";


	auto Start2 = std::chrono::high_resolution_clock::now();

	for (int x = 0; x < MaxIterations; x++)
		std::cout << std::setfill(' ') << std::setw(6) << std::fixed << x << '\r';

	auto Finish2 = std::chrono::high_resolution_clock::now();
	std::cout << endl << MaxIterations << " Iterations with COUT took " << std::chrono::duration_cast<std::chrono::milliseconds>(Finish2 - Start2).count() << "mS\n";
}

				
			

And the results...

				
					19999
20000 Iterations with PRINTF took 881mS
19999
20000 Iterations with COUT took 4630mS
				
			

The printf function was able to print 20,000 integers in 881mS while the gimpy cout clocked in at 4630mS, a whopping 5.25 times slower.

Lets try something a little more challenging, such as printing a formatted floating point number.

Printing 20,000 Floats

				
					using namespace std;
#include <stdio.h>
#include <iostream>
#include <iomanip>
#include <chrono>

int main()
{
	int MaxF = 10000;

	auto Start1 = std::chrono::high_resolution_clock::now();
	for (float f = 0; f < MaxF; f+=0.5)
	{
		printf("%5.2f\r", f);
	}
	auto Finish1 = std::chrono::high_resolution_clock::now();
	std::cout << endl << MaxF * 2 << " Iterations with PRINTF took " << std::chrono::duration_cast<std::chrono::milliseconds>(Finish1 - Start1).count() << "mS\n";


	printf("\n");

	auto Start2 = std::chrono::high_resolution_clock::now();

	for (float f = 0; f < MaxF; f += 0.5)
	{
		std::cout << std::setfill(' ') << std::setw(5) << std::fixed << std::setprecision(2) << f << '\r';
	}

	auto Finish2 = std::chrono::high_resolution_clock::now();
	std::cout << endl << MaxF*2 << " Iterations with COUT took " << std::chrono::duration_cast<std::chrono::milliseconds>(Finish2 - Start2).count() << "mS\n";
}

				
			
				
					9999.50
20000 Iterations with PRINTF took 1015mS

9999.50
20000 Iterations with COUT took 5298mS
				
			

While the printf function turned in a respectable 1015mS to print 20,000 floating-point numbers with padding and truncation, cout turned in a paltry 5298mS – a full 5 times slower.

 

Type Safety

Every once in a while a programmer will make a mistake.  Its true.  One such mistake is mismatching types when using printf.  Here’s an example.

				
						printf("%f is a float!\n", "Oops");
				
			

Instructing printf to work with a float, %f, then providing a string pointer will compile, with warnings, but could be unpredictable at best and crash at worst.

By its nature, cout is type safe, meaning, it won’t even compile without first ensuring it can handle the types of variables you’re throwing at it.

Conclusion

While cout has its uses, it’s clearly outclassed by its older ancestor, printf.

I’ve shown that printf can increase your output by 5 times under heavy load and is simpler to read and write.

Learning printf in today’s programming environment is a worthwhile endevour and will pay back in faster, more readable programs.

As it turns out, “new things” aren’t always replacements for “old things” and in this case, printf is still the king.