7

昨天我有一次面试,面试官问我存储变量的存储类。

我的回答战争:

Local Variables are stored in Stack.       
Register variables are stored in Register
Global & static variables are stored in data segment.  
The memory created dynamically are stored in Heap.

他问我的下一个问题是:为什么它们会存储在那些特定的内存区域中?为什么Local variable 没有被存储register(尽管我需要auto在我的程序中非常频繁地使用一个变量)?或者为什么全局或静态变量被not存储在stack

然后我就一头雾水了。请帮我。

4

5 回答 5

16

因为存储区域决定了变量 的作用域生命周期。

您可以根据您的要求选择存储规范,即:
Lifetime:您期望特定变量需要处于活动状态且有效的持续时间。
范围:您希望变量可访问的范围(区域)。

简而言之,每个存储区域提供不同的功能,您需要不同的功能因此不同的存储区域。

于 2012-05-25T06:13:16.763 回答
14

实际上,C 语言并没有定义任何变量的存储位置。但是,它确实定义了三个存储类:静态、自动和动态。

静态变量是在程序初始化期间(在 之前main())创建的,并且在程序终止之前一直存在。文件范围(“全局”)和静态变量属于该类别。虽然这些通常存储在数据段中,但 C 标准并不要求这种情况,并且在某些情况下(例如,C 解释器)它们可能存储在其他位置,例如堆。

自动变量是在函数体中声明的局部变量。它们在程序流到达其声明时或之前创建,并在超出范围时销毁;这些变量的新实例是为递归函数调用创建的。堆栈是实现这些变量的便捷方式,但同样,它不是必需的。如果您愿意,您也可以在堆中实现自动操作,并且它们通常也放置在寄存器中。在许多情况下,自动变量将在其生命周期内在堆栈和堆之间移动。

请注意,register自动变量的注释是一个提示——编译器没有义务对它做任何事情,事实上许多现代编译器完全忽略了它。

最后,动态对象(C 中没有动态变量之类的东西)指的是使用 或其他类似的分配函数显式创建的malloccalloc。它们在显式创建时存在,并在显式释放时被销毁。堆是放置这些的方便位置 - 或者更确切地说,根据执行这种分配方式的能力定义堆。但同样,编译器实现可以自由地做它想做的任何事情。如果编译器可以执行静态分析来确定动态对象的生命周期,它可能能够将其移动到数据段或堆栈(但是,很少有 C 编译器进行这种“转义分析”)。

这里的关键点是 C 语言标准只定义给值存在的时间。以及这一生命周期的最低限度——它可能会比要求的时间长。究竟如何将它放在内存中是一个主题,其中语言和库实现具有很大的自由度。

于 2012-05-25T06:18:32.347 回答
1

它实际上只是一个方便的实现细节。

如果他愿意,编译器可以在堆上生成局部变量。

在堆栈上创建它们更容易,因为在离开函数时,您可以根据堆栈的增长方向通过简单的加/减来调整帧指针,从而自动释放已使用的空间以供下一个函数使用。然而,在堆上创建本地人意味着更多的家务工作。

另一点是不能在堆栈上创建局部变量,如果编译器认为这样更合适并且有足够的寄存器可以这样做,它们可以只在寄存器中存储和使用。

于 2012-05-25T06:19:43.660 回答
0

在大多数情况下,局部变量存储在寄存器中,因为当您进行函数调用时,寄存器是从堆栈中压入和弹出的。看起来它们在堆栈上。

实际上没有寄存器变量之类的东西,因为它只是 C 中一些很少使用的关键字,它告诉编译器尝试将其放入寄存器中。我认为大多数编译器只是忽略了这个关键字。

那为什么问你更多,因为他不确定你是否深入了解主题。事实上,寄存器变量实际上是在堆栈上。

于 2012-05-25T06:20:52.187 回答
0

在嵌入式系统中,我们有不同类型的存储器(只读非易失性(ROM),读写非易失性(EEPROM,PROM,SRAM,NVRAM,闪存),易失性(RAM))使用,而且我们有不同的要求(不能改变并且在电源循环后仍然存在,可以更改并且在电源循环后仍然存在,可以随时更改)我们拥有的数据。我们有不同的部分,因为我们必须乐观地将我们对数据的需求映射到不同类型的可用内存。

于 2013-06-19T07:34:54.393 回答