Почему двоичный файл C ++ Hello World больше, чем эквивалентный C-бинарный?

В своем FAQ, Bjarne Stroustrup говорит, что при компиляции с gcc -O2 размер файла hello world с использованием C и C ++ идентичен.

Ссылка: http://www.stroustrup.com/bs_faq.html#Hello-world

Я решил попробовать это, вот версия C:

#include  int main(int argc, char* argv[]) { printf("Hello world!\n"); return 0; } 

И вот версия C ++

 #include  int main(int argc, char* argv[]) { std::cout << "Hello world!\n"; return 0; } 

Здесь я компилирую, и размеры разные:

 r00t@wutdo:~/hello$ ls hello.c hello.cpp r00t@wutdo:~/hello$ gcc -O2 hello.c -o c.out r00t@wutdo:~/hello$ g++ -O2 hello.cpp -o cpp.out r00t@wutdo:~/hello$ ls -l total 32 -rwxr-xr-x 1 r00t r00t 8559 Sep 1 18:00 c.out -rwxr-xr-x 1 r00t r00t 8938 Sep 1 18:01 cpp.out -rw-r--r-- 1 r00t r00t 95 Sep 1 17:59 hello.c -rw-r--r-- 1 r00t r00t 117 Sep 1 17:59 hello.cpp r00t@wutdo:~/hello$ size c.out cpp.out text data bss dec hex filename 1191 560 8 1759 6df c.out 1865 608 280 2753 ac1 cpp.out 

Я заменил std::endl на \n и сделал двоичный файл меньше. Я понял, что это простое было бы включено, и я разочарован, это не так.

Также вау, оптимизированные сборки имеют сотни строк сборки? Я могу написать мир привет, как 5 инструкций по сборке, используя sys_write, что со всеми лишними вещами? Почему C устанавливает некоторые дополнительные функции в стек для настройки? Я имею в виду, как 50 байтов сборки против 8kb C, почему?

Вы смотрите на смесь информации, которая легко неверно истолковывается. Размеры файлов 8559 и 8938 байтов в значительной степени бессмысленны, поскольку они в основном являются заголовками с именами символов и другой разной информацией, по крайней мере, для минимальных целей отладки. Несколько значимых чисел – это size(1) вы добавили позже:

 r00t@wutdo:~/hello$ size c.out cpp.out text data bss dec hex filename 1191 560 8 1759 6df c.out 1865 608 280 2753 ac1 cpp.out 

Вы можете получить более подробную разбивку, используя параметр -A для size , но, в общем, различия здесь довольно тривиальны.

Что более интересно, так это то, что Бьярне Страуструп никогда не упоминал, говорил ли он о статической или динамической связи. В вашем случае обе программы динамически связаны, поэтому различия в размерах не имеют ничего общего с фактической стоимостью stdio или iostream; вы просто измеряете стоимость вызывающего кода или (скорее всего, основываясь на других комментариях / ответах) базовые издержки на поддержку обработки исключений для C ++. Теперь есть общее утверждение о том, что основанный на статичных связях мир приветствий на основе iOS-объектов на C ++ может быть даже меньше, чем на основе printf , поскольку компилятор может точно определить, какие перегруженные версии operator<< используются и оптимизировать ненужный код ( таких как дорогостоящая печать с плавающей запятой), в то время как использование printf строк формата делает это трудным в общем случае и вообще невозможно. Тем не менее, я никогда не видел реализацию на C ++, где статическая связанная программа приветствия на основе iostream могла приближаться почти к тому, чтобы быть таким же маленьким, как и меньше, чем на основе printf на C.

Я думаю, что он обрабатывает половину килобайта как ошибку округления. Оба являются «9 килобайтами», и это то, что вы увидите в типичном файловом браузере. Они не совсем то же самое, потому что под капотом библиотеки C и C ++ совершенно разные. Если вы уже знакомы с вашим дизассемблером, вы можете увидеть детали разницы для себя.

«Дополнительный материал» предназначен для импорта символов из стандартной библиотеки shlib и обработки исключений C ++. Как ни странно, большая часть скомпилированного C-исполняемого файла CCC обрабатывается таблицами обработки исключений C ++. Я не понял, как их использовать, используя GCC.

endl inlined, но он содержит вызовы для печати символа \n и streamи streamа, которые не включены. Разница в размере связана с импортом из стандартной библиотеки.

По правде говоря, отдельные килобайты редко имеют значение в любой системе с динамически загружаемыми библиотеками. Самодостаточный код, например, встроенная система, должен включать в себя стандартную библиотечную функциональность, которую он использует, а стандартная библиотека C ++ имеет тенденцию быть более тяжелой, чем ее коллега C – vs. в частности.