C# 值类型变量是否违反堆栈的后进先出特性

C# 值类型变量是否违反堆栈的后进先出特性,c#,variables,memory,stack,allocation,C#,Variables,Memory,Stack,Allocation,例如,我给值类型赋值 int i=0; int j=1; 由于int是一个值类型变量,内存在堆栈中分配如下(将I和j的值推送到堆栈): | |您需要考虑以下信息: C#是一种即时编译语言,.NET CLR负责在程序执行期间从.NET代码生成机器代码 现代CPU有一个寄存器集,它被大量使用,以避免每次操作都需要堆栈 因此,在您的代码中,.NET CLR很可能会将i和j变量放入寄存器中,并且很可能会安排代码,以便只有在没有更多寄存器可使用时,才会将临时变量放入堆栈中 然而,堆栈不是一个简单的后进先

例如,我给值类型赋值

int i=0;
int j=1;
由于
int
是一个值类型变量,内存在堆栈中分配如下(将I和j的值推送到堆栈):


| |您需要考虑以下信息:

  • C#是一种即时编译语言,.NET CLR负责在程序执行期间从.NET代码生成机器代码
  • 现代CPU有一个寄存器集,它被大量使用,以避免每次操作都需要堆栈
  • 因此,在您的代码中,.NET CLR很可能会将i和j变量放入寄存器中,并且很可能会安排代码,以便只有在没有更多寄存器可使用时,才会将临时变量放入堆栈中


    然而,堆栈不是一个简单的后进先出结构。可以使用EBP和ESP寄存器分别作为基偏移量来访问堆栈变量。

    创建和读取局部变量时,不会推送和弹出它们

    该方法的开头是创建堆栈框架以为局部变量腾出空间的代码。这是通过移动堆栈指针在堆栈上创建方法可以使用的内存区域来完成的

    每个局部变量从一开始就在堆栈帧中有一个固定的位置,即使变量的范围小于方法。堆栈帧在方法执行期间不会更改

    |                        |
    | More stack data        |
    |                        |
    +------------------------+
    | Method return address  |
    +------------------------+
    | i                      | Stack frame
    | j                      |
    +------------------------+
    <--- stack pointer
    
    ||
    |更多堆栈数据|
    |                        |
    +------------------------+
    |方法返回地址|
    +------------------------+
    |i |堆栈框架
    |j|
    +------------------------+
    
    你的心智模式被严重破坏,你把“堆叠”这个词看得太字面了。仅当一个方法调用另一个方法时,处理器堆栈的行为类似于堆栈。在方法中,参数和局部变量存储在
    堆栈框架中。它是可自由寻址的,没有推送或弹出。始终作为基址指针寄存器或堆栈指针寄存器的偏移量。32位代码中的EBP,64位代码中的RSP。堆栈帧的大小取决于局部变量的数量。它是通过将堆栈指针减少帧大小来“分配”的。只需恢复堆栈指针即可“销毁”

    如果将其建模为C#
    堆栈
    数据结构,则会更接近


    这应该有助于澄清概念。

    您能解释一下吗:
    在第0个位置,在添加了它应该在第1个位置分配的值之后,该值现在应该是0
    ?为什么您认为第二行不只是使用“第0个位置”?如果你说“我是第0位”,为什么我突然跳到第1位?
    |                        |
    | More stack data        |
    |                        |
    +------------------------+
    | Method return address  |
    +------------------------+
    | i                      | Stack frame
    | j                      |
    +------------------------+
    <--- stack pointer