其中变量的值存储在C中

时间:2013-05-16 05:07:02

标签: c linux windows compiler-construction

在以下代码段中:

int func()
{
    int a=7;
    return a;
}

值7的代码段是否存储在可执行文件中?或者它是在数据段还是在代码段中?答案取决于操作系统或编译器吗?

3 个答案:

答案 0 :(得分:3)

每种可执行格式都有一些部分。其中一个是text,包含程序集 - 二进制代码。其中一个是heap,其中找到malloc - ed数据,其中stack存储了局部变量。还有其他几个,但现在没关系。以上三种在各地都很常见。

现在,像a这样的本地数据驻留在堆栈上。在可执行文件中,该值存储在text部分。

我在您的代码中添加了main(返回0),使用-g编译然后objdump -CDgS a.out并搜索了0x424242(我已经替换了您的{ {1}}具有在代码中随机出现的可能性较小的值。)

7

如您所见,00000000004004ec <func>: int func() { 4004ec: 55 push %rbp 4004ed: 48 89 e5 mov %rsp,%rbp int a=0x42424242; 4004f0: c7 45 fc 42 42 42 42 movl $0x42424242,-0x4(%rbp) return a; 4004f7: 8b 45 fc mov -0x4(%rbp),%eax } 4004fa: 5d pop %rbp 4004fb: c3 retq 表示该值存储在生成的文件中。实际上,通过c7 45 fc 42 42 42 42

查看二进制文件就是这种情况
xxd

您可以在$ xxd a.out | grep 4242 00004f0: c745 fc42 4242 428b 45fc 5dc3 5548 89e5 .E.BBBB.E.].UH.. 代码段中识别上述装配线。

答案 1 :(得分:2)

由于a隐含auto(即不是externstatic),因此会将其存储在call stack框架中。

实际上,编译器可能会优化:在您的情况下,在优化时,它可能会保留在寄存器中(或者是常量传播和常量折叠):不需要为{{1}分配调用堆栈槽}}

这当然是编译器,目标平台和操作系统相关的。对于GCC编译器,了解Gimple内部表示(通过a或使用MELT probe)并查看生成的汇编代码(使用-fdump-tree-all

另请参阅this answer,其中提供了大量参考资料。


Linux / x86-64上的GCC 4.8将您的函数编译成-fverbose-asm -S -O):

gcc -S -fverbose-asm -O

所以你看到在你的特定情况下没有为 .globl func .type func, @function func: .LFB0: .cfi_startproc movl $7, %eax #, ret .cfi_endproc .LFE0: .size func, .-func 使用额外的空间,它直接存储在7中,它是寄存器(在ABI约定中定义)来保存其返回的结果。

%eax存储在7机器指令内的机器代码中。执行movl时,该7将加载到包含返回结果func的注册表%eax中。

答案 2 :(得分:0)

根据示例代码,变量“a”进入调用堆栈,放置存储局部变量以及函数调用信息,如程序计数器,返回地址等