Page 1 of 2

I am amased...

Posted: Tue May 29, 2007 11:47 am
by Zacariaz
Little did i know that the difference between C and C++ was this great.
I made two hello world programs

In C

Code: Select all

#include <stdio.h>

int main() {
  printf( "I am alive!  Beware.\n" );
  getchar();
  return 0;
}
and in C++

Code: Select all

#include <iostream>

int main() {
  std::cout << "I am alive!  Beware." << std::endl;
  std::cin.get();
  return 0;
}
Seemingly they are the same (im not 100% sure of it) but the difference in size after compiled is huge 15.4KB vs. 463KB

My plan was to take a look at the debug code, but 463 is to much for me, so i was thinking if anyone could explain a litle about where the differences lye, and allso if the two pieces of code are really as close to each other as you get.

Posted: Tue May 29, 2007 11:57 am
by jnc100
The main difference is here:
Zacariaz wrote:

Code: Select all

#include <iostream>
If you remove that line it drops to around 16 kB.

I guess the iostream header includes many, many more.

Although compiling the C version with g++ does add 1015 bytes to it over the output of gcc.

Regards,
John.

Posted: Tue May 29, 2007 11:58 am
by senaus
That's probably because of all the bloated STL code being linked in. I converted my kernel to C++ recently and the code size hardly changed, it's the libs that add the bloat!

Posted: Tue May 29, 2007 11:58 am
by Zacariaz
ok, im no super programmer, but i didnt actually think it included the whole header.

Posted: Tue May 29, 2007 12:03 pm
by jnc100
Zacariaz wrote:ok, im no super programmer, but i didnt actually think it included the whole header.
You're right, but somewhere in that huge mess of includes it references there's probably a pragma to include a library or two. Just have to find it...

Posted: Tue May 29, 2007 12:10 pm
by Zacariaz
K, but the main thing, i guess, is that C is much better at handling those headers than C++? Or is that the wrong impression?

Posted: Tue May 29, 2007 12:25 pm
by Candy
Zacariaz wrote:K, but the main thing, i guess, is that C is much better at handling those headers than C++? Or is that the wrong impression?
That's very wrong yep.

C includes no static objects, no long function names (only required 32 characters to work for that matter) and so on. C++ requires static object (std::cout is a static object of a complex type, std::cerr is an object) and much longer names for the variables since they're in namespaces and need to be kept out of the C name space. It also commonly includes a lot of standard support for things your application might receive depending on the environment, such as exception handling and run-time type identification. You also probably include a bit of debug or such. Look at the object with objdump and find out what's what exactly - try looking at the section headers mostly, they tell you how big each part is.

Compiling the C application with the C++ compiler makes it mangle the names as C++ would do. I compile my entire kernel with the c++ version to take advantage of overloading.

Posted: Tue May 29, 2007 12:29 pm
by Candy
I can't reproduce your behaviour here:

-rwxr-xr-x 1 candy users 8134 2007-05-29 20:40 hello*
-rw-r--r-- 1 candy users 98 2007-05-29 20:40 hello.c
-rwxr-xr-x 1 candy users 10628 2007-05-29 20:40 hello2*
-rw-r--r-- 1 candy users 118 2007-05-29 20:40 hello2.cc

After stripping:

-rwxr-xr-x 1 candy users 2956 2007-05-29 20:42 hello*
-rw-r--r-- 1 candy users 98 2007-05-29 20:40 hello.c
-rwxr-xr-x 1 candy users 4652 2007-05-29 20:42 hello2*
-rw-r--r-- 1 candy users 118 2007-05-29 20:40 hello2.cc

Posted: Tue May 29, 2007 12:33 pm
by Zacariaz
Ok, i think i more or less get it, however one question still remains.
I am using the dev-c++ compiler (bloodshed ide) would it makes a notisable difference using a c compiler instead?

And thanks for the answers.

Posted: Tue May 29, 2007 1:53 pm
by Combuster
begin with setting the "strip executable" option to yes. That will probably save you more than switching to C. Its in Project -> Project Options -> Compiler tab -> Linker.

In my case, it shrank a small opengl test app from 419k to 11k (just tested)

@Candy: Windows obviously isnt linux...

Posted: Tue May 29, 2007 2:15 pm
by jnc100
My figures were with MinGW. I stripped the C++ version, but it still came to over 200kB. Running nm on it shows just how much stuff is needed just to run this program.

Posted: Tue May 29, 2007 2:21 pm
by Zacariaz
wow, that did make a difference, thanks alot.

Posted: Wed May 30, 2007 12:41 am
by Solar
Some more words on this. I am using Cygwin GCC 3.4.4.

Code: Select all

#include <stdio.h> 

int main() { 
  printf( "I am alive!  Beware.\n" ); 
  getchar(); 
  return 0; 
}
Unstripped 9167 bytes, stripped 3072 bytes.

Code: Select all

#include <cstdio> 

int main() { 
  std::printf( "I am alive!  Beware.\n" ); 
  std::getchar(); 
  return 0; 
}
Unstripped 9014 bytes, stripped 3072 bytes.

Finding #1: Just running GCC in C++ mode doesn't add to the binary size.

Code: Select all

#include <cstdio>
#include <string>

int main() { 
  std::printf( "I am alive!  Beware.\n" ); 
  std::getchar(); 
  return 0; 
}
Unstripped 9014 bytes, stripped 3072 bytes.

Finding #2: Adding a C++ header does not add to the binary size.

Code: Select all

#include <iostream>
#include <cstdio>

int main() { 
  std::printf( "I am alive!  Beware.\n" ); 
  std::getchar(); 
  return 0; 
}
Unstripped 477999 bytes, stripped 276992 bytes.

Whoa, what happened there?

The answer is: Global objects (as Candy said).

The C subset example didn't need to link anything C++-specific. But <iostream> gives you cin and cout (and cerr and clog and the wide-character counterparts), which have to be initialized no matter whether you use them or not. This in turn requires the supporting C++ runtime: Global constructor calling and exception support, mostly.

"Yuck, why should I use C++ then?"

The answer is threefold.

One, most of this is a one-time cost. We are not looking at a size factor of 100 here, but a fixed cost of 200k supporting code. For any non-trivial application, the cost of exception support in code size is neglectable compared to the application proper. With good C++ code, you will actually reach a break-even point pretty soon where the C++ exception support is smaller than the code required in C to check each and every return code.

Two, if you don't want to use the library or exceptions, you can simply disable them altogether. It's all about choice.

Three, abstraction. I'll let code speak for me here.

Code: Select all

cout << x; // print x regardless of what type it is. Try this in C.

Posted: Sat Jul 14, 2007 3:07 am
by AndrewAPrice
You can include stdio.h in C++ and use printf. But 463KB for a C++ Hello World and 15.4KB for C? That doesn't sound right. Everything which runs in kernel mode in my OS is written in C++ and it's only 16KB.

Posted: Mon Jul 16, 2007 8:00 pm
by Twitch
I ran the test.
I'm on linux using gcc and g++ and I get almost no difference
c 6.5 kb
c++ 7.9 kb

And I'm using iostream not cstdio with no optimizations .

maybe it's the compiler?
from Bjarne Stroustrup
Why is the code generated for the "Hello world" program ten times larger for C++ than for C?
It isn't on my machine, and it shouldn't be on yours. I have even seen the C++ version of the "hello world" program smaller than the C version. When I recently (2004) tested using gcc -o2 on a Unix, the two versions (iostreams and stdio) yielded identical sizes. There is no language reason why the one version should be larger than the other. It is all an issue on how the implementor organized the libraries. If one version is significantly larger than the other, report the problem to the implementor of the larger.