c++ - 为什么 C 头文件不增加二进制文件的大小?

标签 c++ executable header-files

我编写了以下 C++ 程序

class MyClass {
public:
        int i;
        int j;
        MyClass() {};
};

int main(void)
{
        MyClass inst;
        inst.i = 1;
        inst.j = 2;
}

我编译了。

# g++ program.cpp
# ls -l a.out
-rwxr-xr-x  1 root  wheel  4837 Aug  7 20:50 a.out

然后,我在源文件中#included头文件iostream,我再次编译。

# g++ program.cpp
# ls -l a.out
-rwxr-xr-x  1 root  wheel  6505 Aug  7 20:54 a.out

正如预期的那样,文件大小增加了。

我还写了下面的C程序

int main(void)
{
    int i = 1;
    int j = 2;
}

我编译了

# gcc program.c
# ls -l a.out
-rwxr-xr-x  1 root  wheel  4570 Aug  7 21:01 a.out

然后,我#included头文件stdio.h,我再次编译

# gcc program.c
# ls -l a.out
-rwxr-xr-x  1 root  wheel  4570 Aug  7 21:04 a.out

奇怪的是,可执行文件的大小保持不变。

最佳答案

通过在源文件中包含 iostream,编译器需要生成代码来设置和拆除 C++ 标准 I/O 库。您可以通过查看 nm 的输出来看到这一点,它显示了目标文件中的符号(通常是函数):

$ nm --demangle test_with_iostream
08049914 d _DYNAMIC
08049a00 d _GLOBAL_OFFSET_TABLE_
08048718 t global constructors keyed to main
0804883c R _IO_stdin_used
         w _Jv_RegisterClasses
080486d8 t __static_initialization_and_destruction_0(int, int)
08048748 W MyClass::MyClass()
         U std::string::size() const@@GLIBCXX_3.4
         U std::string::operator[](unsigned int) const@@GLIBCXX_3.4
         U std::ios_base::Init::Init()@@GLIBCXX_3.4
         U std::ios_base::Init::~Init()@@GLIBCXX_3.4
080485cc t std::__verify_grouping(char const*, unsigned int, std::string const&)
0804874e W unsigned int const& std::min<unsigned int>(unsigned int const&, unsigned int const&)
08049a3c b std::__ioinit
08049904 d __CTOR_END__
... (remaining output snipped) ...

(--demangle 采用编译器“修改”过的 C++ 函数名称并生成更有意义的名称。如果函数包含在可执行文件中,则第一列是地址。第二列column 是类型。“t”是“text”段中的代码。“U”是从其他地方链接的符号;在这种情况下,来自 C++ 共享库。)

将此与从源文件生成的函数进行比较,不包括 iostream:

$ nm --demangle test_without_iostream
08049508 d _DYNAMIC
080495f4 d _GLOBAL_OFFSET_TABLE_
080484ec R _IO_stdin_used
         w _Jv_RegisterClasses
0804841c W MyClass::MyClass()
080494f8 d __CTOR_END__
... (remaining output snipped) ...

当您的源文件包含 iostream 时,编译器会生成几个没有 iostream 时不存在的函数。

当您的源文件仅包含 stdio.h 时,生成的二进制文件类似于没有 iostream 的测试,因为 C 标准 I/O 库不需要超出 C 动态库中已经发生的任何额外初始化。您可以通过查看 nm 输出来看到这一点,它是相同的。

不过,一般来说,试图根据可执行文件的大小来直观地了解特定源文件生成的代码量是没有意义的。有太多东西可以改变,如果编译器包含调试信息,源文件的位置等简单的事情可能会改变二进制文件。

您还可能会发现 objdump 对于查看可执行文件的内容很有用。

关于c++ - 为什么 C 头文件不增加二进制文件的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1246260/

相关文章:

c++ - 如何 vector<int> += 1,1,2,2,2,3,4,5,6;可能的?

c++ - 什么是编译时多态性,为什么它只适用于函数?

c - 使用C程序将可执行文件制作成shell命令

android - 如何从我的 LIBGDX 游戏中制作可执行文件

c++ - 关于 C++ 头文件包含的基本问题?

c++ - 使用 BOOST property_tree/iostreams/filesystem/foreach - 结果出现链接错误

c++ - 如何解析多行的字符串对?

c++ - 复制的可执行文件是否会在没有库的情况下在新机器上运行

c - 头文件错误 : incomplete type is not allowed

c - 解析 C 头文件以提取有关数据类型、函数和函数参数的信息