当我们声明一个变量(例如int)时,我想知道在内存分配和初始化过程中涉及的步骤。还有一个指针
int x = 5;
现在在编译期间,将4个字节分配给整数x。但是何时将内存填充为值5?在编译或运行时执行期间是否进行初始化? 同样地,考虑
int x = 5;
int* p = &x;
在这两行中,分配和初始化的过程是什么。
答案 0 :(得分:0)
变量初始化取决于变量的种类。全局或静态变量在编译时初始化,而自动变量在运行时完全管理。
全局变量
在编译时,所有全局变量的值都是已知的。这些值由编译器写入目标文件的特定部分。
在链接时,将收集所有目标文件,并为每个变量确定存储位置。如果这些地址之一分配给另一个变量,则可以知道每个变量的地址。
结果,将生成一个可执行文件,其中包含每个部分的内容的描述(文本,数据,rodata等)。在data或rodata部分中,写入所有初始化的全局变量的值。
在运行时,加载程序读取不同部分的描述并询问OS内存。然后它将所有节的内容复制到它们各自的存储位置。
这是用在编译或链接时确定的值初始化变量的方式。
唯一的例外是初始化为零(或未初始化)的变量。它们位于一个特殊的部分(通常称为bss)中。为了减小可执行文件的大小,这些零值未写入可执行文件中。相反,在执行main()
之前,运行时过程会将bss节的所有内容设置为零。
自动变量
过程完全不同。在程序运行之前,还不知道这些变量的位置,唯一的方法是通过机器指令来计算它们的值。
因此,编译器首先确定这些var是否位于寄存器或内存中,并且在进入函数时,第一条指令将是为局部变量保留堆栈空间并初始化它们的值。这是通过常规机器指令完成的。
如果该值是另一个变量的地址(例如y =&x),
*如果x是局部(自动)变量,则通过将栈指针寄存器的内容与编译器确定的给定偏移量之和写入y
来计算地址。
*如果x是全局变量或静态变量,则在链接时,一旦知道全局变量的地址,链接器就会修改编译器生成的指令,以在用于表示{{1}的寄存器或堆栈位置中写入正确的地址}。
答案 1 :(得分:0)
在某些情况下,无法在运行时进行定义: 如果user_input ==“是”: my_var = 5 其他: my_var = 7
但是通常这取决于负责的编译器程序员已经实现的概念。如果您使用其他编译器或语言,则情况可能会有所不同。