我正在尝试学习C程序的可执行文件的结构.我的环境是GCC和64位Intel处理器.
请考虑以下C代码a.cc.
#include <cstdlib>
#include <cstdio>
int x;
int main(){
printf("%d\n", sizeof(x));
return 10;
}
Run Code Online (Sandbox Code Playgroud)
该size -o a节目
text data bss dec hex filename
1134 552 8 1694 69e a
Run Code Online (Sandbox Code Playgroud)
我添加了另一个初始化的全局变量y.
int y=10;
Run Code Online (Sandbox Code Playgroud)
该size a节目(其中a从a.cc可执行文件的名称)
text data bss dec hex filename
1134 556 12 1702 6a6 a
Run Code Online (Sandbox Code Playgroud)
我们知道,该BSS部分存储未初始化的全局变量的大小并DATA存储已初始化的变量.
int在BSS中占用8个字节?将sizeof(x)在我的代码表明,int实际占用了4个字节.int y=10添加4个字节数据,是有道理的,因为int应该采取4个字节.但是,为什么它会为BSS增加4个字节?size删除两行后,两个命令之间的差异保持不变#include ....
更新:
我认为我对BSS的理解是错误的.它可能不存储未初始化的全局变量.正如维基百科所说:"BSS在运行时需要的大小记录在目标文件中,但BSS(与数据段不同)不会占用目标文件中的任何实际空间." 例如,即使是一行C代码int main(){}也有bss 8.
BSS的8或16是否来自alignment?
它没有,它占用4个字节而不管它在哪个段.你可以使用nm带有-S参数的工具(来自GNU binutils包)来获取目标文件中所有符号的名称和大小.您可能会看到编译器的次要影响,包括或不包括某些其他符号,无论出于何种原因.
例如:
$ cat a1.c
int x;
$ cat a2.c
int x = 1;
$ gcc -c a1.c a2.c
$ nm -S a1.o a2.o
a1.o:
0000000000000004 0000000000000004 C x
a2.o:
0000000000000000 0000000000000004 D x
Run Code Online (Sandbox Code Playgroud)
一个目标文件具有x在未初始化数据段(C)中命名的4字节对象,而另一个目标文件具有x在初始化数据段(D)中命名的4字节对象.