printf() v/s cout....which one is better?
I just started writing this tutorial...and here's the current unfinished version showing the winner when it comes to "code generation". I'll post further updates soon as I finish writing them...
Enjoy!!!
P.S -> Please Correct Me if I am wrong in certain places....
Many people still think that printf and scanf belongs to C while cout and cin
belongs to C++ and so they avoid using printf and scanf while writing programs
in C++. Of-course you cant do this viceversa but depending on the design of your
program you should use printf and cout accordingly. This is because printf
though cryptic and complex in it's nature takes up a lot fewer bytes than what
cout hogs up. This is exactly what this article does. This Article will show you
which function is better under a certain situation. You will need a disassembler
or a debugger to carry on with this Article. IDA Pro and OllyDebug are
recommended for understanding this article. W32DASM can be used as well. If
you don't have a copy of these, you can contact me at born2c0de@hotmail.com
So Let's begin without wasting any time.
I. CONSTANTS AND LITERALSOur first test is to see which function takes up the least amount of space as
far as printing out constants or literalsis concerned. Consider this following
program:
CODE
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
cout<<"THIS IS A LITERAL\n";
printf("THIS IS A LITERAL\n");
int i=10;
cout<<i<<endl;
printf("%d\n",i);
return 0;
}
Here is it's Disassembled Listing generated by Interactive Disassembler 4.50 Pro:
CODE
; int __cdecl main(int argc,const char **argv,const char *envp)
_main proc near; DATA XREF: .data:0040D0E0o
argc = dword ptr 8
argv = dword ptr 0Ch
envp = dword ptr 10h
.text:00401108 push ebp
.text:00401109 mov ebp, esp
.text:0040110B push ebx
; ----------------------------THE COUT FUNCTION STARTS HERE
.text:0040110C[2] push 0
.text:0040110E[5] push offset aThisIsALiteral;"THIS IS A LITERAL\n"
.text:00401113[5] push offset unk_40FEDC
.text:00401118[5] call @ostream@outstr$qpxct1;ostream::outstr(char *,char *)
.text:0040111D[3] add esp, 0Ch
; ----------------------------THE COUT FUNCTION ENDS HERE
; ----------------------------PRINTF STARTS HERE
.text:00401120[5] push offset aThisIsALiter_0;format
.text:00401125[5] call _printf
.text:0040112A[1] pop ecx
; ----------------------------PRINTF ENDS HERE
.text:0040112B mov ebx, 0Ah
; ----------------------------COUT STARTS HERE
.text:00401130[2] mov eax, ebx
.text:00401132[1] push eax
.text:00401133[5] push offset unk_40FEDC
.text:00401138[5] call @ostream@$blsh$ql; ostream::operator<<(long)
.text:0040113D[3] add esp, 8
.text:00401140[1] push eax
.text:00401141[5] call @endl$qr7ostream; endl(ostream &)
.text:00401146[1] pop ecx
; ----------------------------COUT ENDS HERE
; ----------------------------PRINTF STARTS HERE
.text:00401147[1] push ebx
.text:00401148[5] push offset aD; format
.text:0040114D[5] call _printf
.text:00401152[3] add esp, 8
; ----------------------------PRINTF ENDS HERE
.text:00401155 pop ebx
.text:00401156 pop ebp
.text:00401157 retn
_main endp
.data:0040D110 aThisIsALiteral db 'THIS IS A LITERAL',0Ah,0; DATA XREF: _main+6o
.data:0040D123 aThisIsALiter_0 db 'THIS IS A LITERAL',0Ah,0; DATA XREF: _main+18o
.data:0040D136 aD db '%d',0Ah,0; DATA XREF: _main+40o
.data:0040FEDC unk_40FEDC db ?;; DATA XREF: _main+Bo
I have given the addresses as well so that you can compute how many bytes an
instruction takes up. From now on, i wont show the addresses. Instead I'll
include the space taken up as bytes in Square Brackets as I have already done
here. Let us now compare the results of both:
LITERAL OUTPUT:
cout -> 20 Bytes
printf -> 11 Bytes [ 55% of cout ]
CONSTANT OUTPUT:
cout -> 23 Bytes
printf -> 14 Bytes [ 60.86% cout ]
OVERALL: printf takes up 58.13% lesser space than cout.
This post has been edited by born2c0de: 6 Oct, 2007 - 06:26 AM