为什么 C++ Hello World 二进制文件比等效的 C 二进制文件大?

2024-01-09

Bjarne Stroustrup 在他的常见问题解答中表示,当使用 gcc -O2 编译时,使用 C 和 C++ 的 hello world 的文件大小是相同的。

参考:http://www.stroustrup.com/bs_faq.html#Hello-world http://www.stroustrup.com/bs_faq.html#Hello-world

我决定尝试一下,这是 C 版本:

#include <stdio.h>

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

这是 C++ 版本

#include <iostream>

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 with \n它使二进制文件变得更小。我认为这么简单的东西会被内联,但我很失望它不是。

另外哇,优化后的程序集有数百行程序集输出?我可以使用 sys_write 用大约 5 条汇编指令编写 hello world,所有额外的东西是怎么回事?为什么C要在堆栈上放置一些额外的东西来设置?我的意思是,就像 50 字节的汇编 vs 8kb 的 C,为什么?


您看到的信息很容易被误解。 8559 和 8938 字节的文件大小基本上没有意义,因为它们主要是带有符号名称和其他杂项信息的标头,至少用于最小的调试目的。这somewhat有意义的数字是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,但简而言之,这里的差异相当微不足道。

更有趣的是,Bjarne Stroustrup 从未提及他是在谈论静态链接还是动态链接。在您的情况下,两个程序都是动态链接的,因此大小差异与 stdio 或 iostream 的实际大小成本无关;您只是测量调用代码的成本,或者(更有可能的是,基于其他注释/答案)C++ 异常处理支持的基本开销。现在,有一个普遍的说法,即静态链接的基于 C++ iostream 的 hello world 甚至可以比printf基于的,因为编译器可以准确地看到哪些重载版本operator<<使用并优化不需要的代码(例如昂贵的浮点打印),而printf格式字符串的使用使得这在常见情况下变得困难并且一般来说是不可能的。然而,我从未见过一个 C++ 实现,其中静态链接的基于 iostream 的 hello 程序可以接近与一个小程序一样小,甚至更小。printf基于 C 的一个。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 C++ Hello World 二进制文件比等效的 C 二进制文件大? 的相关文章

  • C 中的隐秘结构定义

    我遇到了以下情况迷宫定义 https github com gduarte lkb blob master code stack maze h code typedef struct mazeNode int hasCheese int t
  • 输出 objdump -t 的输出中的“.hidden”是什么意思?

    Example objdump Logger cpp o t 00000000 g F text 00000000 hidden sti 10 Logger cpp 0b2ae32b 这意味着符号的可见性被隐藏 https develope
  • 获取枚举实例的名称[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 假设我有这个枚举 public enum MyEnum ValueOne 1 ValueTwo 2 ValueThree 3 然后
  • 如何将 int.TryParse 与可为空的 int 一起使用? [复制]

    这个问题在这里已经有答案了 我正在尝试使用 TryParse 来查找字符串值是否为整数 如果该值为整数 则跳过 foreach 循环 这是我的代码 string strValue 42 if int TryParse trim strVal
  • 如何使用c#/VB.NET在word中插入书签

    我正在尝试使用 C 在 Word 文档中添加书签 但它不起作用 而且我在 msdn 文档和互联网上都找不到任何帮助 这就是我正在尝试做的事情 我正在阅读 Word 文档 然后在该文档中搜索关键字 然后将该文本转换为超链接 效果很好 现在 我
  • 在 C 的公共 API 函数中使用枚举参数是个好主意吗?

    我正在设计一个 C API 其中必须提供一种设置一些双值选项的方法 为了识别选项 我使用以下枚举 typedef enum OptionA OptionB Option 使用是一个好主意吗Option作为公共 API 函数中的参数类型 in
  • 如何使用 LINQ 对列表的列表进行分组(例如:List>)

    我知道我可以使用一些 for 循环轻松地做到这一点 但想看看是否有一种方法可以使用流畅的 LINQ 来做到这一点 我试图找出每个子列表中有多少个 我在看Enumerable SequenceEqual http msdn microsoft
  • 为什么在此单元测试中,BackgroundWorker 没有在正确的线程上调用 RunWorkerCompleted?

    backgroundWorker 的全部目的是在执行耗时的任务后更新 UI 组件正如广告所宣传的那样在我的 WPF 应用程序中 但是在我的测试中 回调不会在调用线程上调用 Test public void TestCallbackIsInv
  • esp8266互联网交换机问题

    我正在尝试制作一个门继电器开关系统 我可以通过端口转发从任何地方进行操作 我找到了一个非常有用的指南和代码 我的程序基于 https openhomeautomation net control a lamp remotely using
  • Visual Studio:同时调试多个项目?

    是否可以在 Visual Studio 中同时调试多个项目 我知道您可以从解决方案属性中选择多个启动项目 但是断点是如何处理的 如果两个项目使用同一个类 它的两个不同实例 并且我因其中的断点而停止 那么它只会阻止一个程序还是同时阻止两个程序
  • 是否可以将 CMFCToolBar 添加到对话框中?

    我刚刚尝试了将 CToolbar 添加到新 CMFCToolBar 上的对话框的标准方法 但这不起作用 在我深入研究新的实现之前 我想知道它是否真的可行 我不确定你所说的 标准方式 是什么意思 但你当然可以以编程方式做到这一点 In MyD
  • 如何在提升日期时间中忽略周末和节假日?

    第一个问题 我有一个提升日期对象 如下所示 boost gregorian date 今天 2012 02 13 我从今天减去日期部分 如下所示 今天 月 240 或今天 天 X 等 我想在进行上述减法时是否有办法排除周末和特殊假期 我的意
  • DirectX Vertex 中的 THE 是什么

    我知道 RHW 是倒数同质 W 但有人可以解释一下它的使用方法和作用吗 gamedev论坛上的说明post http www gamedev net topic 440283 reciprocal of homogeneous w and
  • 在 C99 中,f()+g() 是未定义还是只是未指定?

    我曾经认为在C99中 即使函数的副作用f and g干扰 虽然表达f g 不包含序列点 f and g将包含一些 因此行为将是未指定的 要么 f 在 g 之前调用 要么 g 在 f 之前调用 我不再那么确定了 如果编译器内联函数会怎样 即使
  • 将 boost::iostreams::mapped_file_source 与 std::multimap 一起使用

    我有相当大量的数据需要分析 每个文件大约有 5gig 每个文件的格式如下 xxxxx yyyyy 键和值都可以重复 但键是按升序排列的 我正在尝试使用内存映射文件来实现此目的 然后找到所需的键并使用它们 这是我写的 if data file
  • 为什么在 C++ 内存管理中术语“自动”和“动态”优于术语“堆栈”和“堆”?

    与 SO 上的许多问题和答案相关 我了解到最好将其生命周期管理为驻留在自动存储中而不是堆栈中的对象 此外 动态分配的对象不应该被称为驻留在堆上 而应该被称为驻留在动态存储中 我知道有自动 动态和静态存储 但从未真正理解自动堆栈和动态堆之间的
  • timeval_subtract 解释

    使用 timeval subtract 函数来查找两个 struct timeval 类型之间经过的时间 有人可以解释一下用于 通过更新 y 执行后续减法的进位 和其他部分的目的和逐步数学吗 我了解该函数的目的以及如何在程序中实现它 但我想
  • 如何获取 (Linux) 机器的 IP 地址?

    这个问题和之前问的几乎一样如何获取本地计算机的IP地址 https stackoverflow com questions 122208 get the ip address of local computer 问题 但是我需要找到一个的I
  • 为什么删除void*是UB而不是编译错误?

    为什么要通过删除对象void 是未定义的行为 而不是编译错误 void foo void p delete p 这段代码编译并生成代码 尽管有关于 gcc 和 clang 的警告 令人惊讶的是 ICC 没有给出警告 2 5 warning
  • 同时使用多个控制台

    是否有捷径可寻 我现在仅使用控制台测试我的网络应用程序 最好的办法是从一个项目中拥有多个控制台 然后按一下 立即调试 菜单项 我可以像过去一样使用多个项目 但这似乎很笨拙 理想情况下 我可以启动多个控制台实例 从同一线程运行很好 并且让它们

随机推荐