#include <stdio.h>
int main()
{
int i = 10;
return 0;
}
在上面的程序中,值 10 究竟存储在哪里?
我了解变量 i 存储在堆栈中。在运行时填充堆栈。从“确切的地方” 10 来自。
10 是一个常数,因此编译器将直接在程序的可执行部分中使用数字 10 作为 CPU 指令的一部分。
这是在我的系统上生成的程序集gcc
:
movl $10, -4(%rbp)
(这4
是因为 anint
是 4 个字节长)
请注意,所有这些都是实现的一部分,但上述情况在实践中会发生。语言本身并没有指定这些细节。
10
是一个“字面量”,它会在编译时由编译器生成。然后它将分配给堆栈上的变量。喜欢
mov eax, 10;
mov [0x12345678], eax;
虽然这是伪代码,但会为您的变量i
(地址在这里是 0x12345678)分配值10
,之前存储在eax
.
“堆栈”是操作系统为您的程序留出的内存区域,与“堆”、全局变量和可执行代码分开。
调用函数时,有代码将参数压入堆栈,然后为局部变量留出空间。当函数返回这个空间并且所有参数都从堆栈中“弹出”时,内存可以被下一个函数重用。
这是一个非常基本和粗略的描述,许多细节在系统和编译器之间存在差异。
编译和链接后你的可执行文件包含多个段。这些细分市场有两种类型:
(还有其他类型)
值 10 要么存储在文本段中(作为将 10 设置为特定地址或寄存器的指令),要么作为数据存储在数据段中(由代码检索并存储在特定地址/寄存器中)。
编译器决定什么是最好的(对于给定的编译标志最有效)。但我认为它“存储”在文本段中,因为值 10 很容易“在代码中创建”(如其他一些答案所示)。
更复杂的数据(结构、字符串等)通常存储在数据段中。
将有一个明确的机器代码指令设置i
.
就像是:
MOV AL, 10
值 10 存储在包含源代码的物理源文件中。在执行期间,该值被传输到名为 的变量中i
,该变量具有自动存储持续时间,并且类型为int
。这才是最重要的。任何进一步的问题在通用编程语言(例如 C)领域都没有成效。
注意大多数答案是如何提到编译器的?如果使用解释器将 C 源代码直接翻译成行为会怎样?这些答案仍然有效吗?
如果您愿意,我宁愿不“给男人一条鱼”……您实际上可以自己检查一下:
获取您的代码并从中创建一个目标文件:
> gcc -c file.c -o file.o
然后对生成的文件进行对象转储:
> objdump -d file.o
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 10 sub $0x10,%rsp
8: c7 45 fc 0f 00 00 00 movl $0xa,-0x4(%rbp) // Right here you can see
// the raw value 0xa (10)
// being set, so it's in the
// .text section