C# decimal 的值是否存储在堆中,即使它是局部变量?

Is the value of a C# decimal stored on the heap even when it is a local variable?

问题

一个C#decimal的值是局部变量的时候是存储在堆上吗?

我(相信)知道的

在32位系统上只有4个字节可用的情况下,16字节大的decimal的值如何存储在堆栈中?

我的思路哪里错了?

我读了什么

How can the value of a decimal, which is 16 bytes big, be stored on the stack at all where there are only 4 bytes available on a 32bit system? Where did my thinking go wrong?

您的想法在 "a 32 bit reference fits into 4 bytes" 的某处出错并从 "the stack is 4 bytes long" 得出结论。默认情况下,堆栈的长度为一百万字节;如果运行时决定将一个十进制变量(或值)放在堆栈上,那么它会保留这百万字节中的 16 个。

很好,你正在思考计算机是如何在引擎盖下工作的,但当然不要忘记 C# 团队努力创造一种语言,你不必关心变量是否在堆栈或堆。您必须编写一些非常高级的程序才能发挥作用;我从来没有编写过需要担心堆栈与堆的业务线 C# 程序,而且我已经编写 C# 程序 10 多年了。

更新:

I've updated the image to illustrate that I don't think the entire stack was 4 bytes long but only the one reference "memory box".

好的,很好。再一次,让我们假设一个引用是四个字节,在某些机器上是这样。如果运行时需要在堆栈上放置一个引用,它会在堆栈上保留四个字节。不需要以四字节块的形式保留堆栈。它可以以任意大小的块保留。

所以我会更新我的解释。当您假设 "a reference is four bytes, therefore the stack can only be reserved in four-byte chunks" 时,您就错了。堆栈上可以保留任意数量的字节,从零到一百万。

(请不要尝试保留一百万;坏事会发生。.NET 指南说要制作 16 字节或更少的结构是有原因的!)

现在,出于性能原因,在某些架构上,运行时可能尝试保留堆栈内存,以便每个块 对齐到四字节边界 。如果数据未对齐,某些硬件会非常慢。但这是您在 C# 中几乎永远不需要担心的细节级别。

再次更新:

这是另一种思考方式。假设我们有两个 4 字节整数的普通局部变量:

int x;
int y;

这会得到两个内存块,每个内存块有四个字节。现在假设我们有一个结构:

struct S 
{ 
    public int x; 
    public int y; 
}

然后我们创建一个局部变量:

S s;

与之前完全相同。我们在堆栈上有 两个变量 ,这些变量被命名为 s.xs.y。将一个结构体入栈等于将结构体中的所有字段变量入栈.

又一更新:

另一件可能让您感到困惑的事情是,还有一种叫做 的另一种 临时存储 "registers" ,它也用于存储局部变量,并且真正地注册了只有四个字节长。 (除了那些是 8 的,但我们不要去那里。)一个 16 字节的结构如何存储在寄存器中? 不是。运行时根本不会将大结构放入寄存器。