C# decimal 的值是否存储在堆中,即使它是局部变量?
Is the value of a C# decimal stored on the heap even when it is a local variable?
问题
一个C#decimal
的值是局部变量的时候是存储在堆上吗?
我(相信)知道的
-
decimal
struct has 16 bytes.
ValueType
类型的局部变量的值存储在栈中,decimal
继承自ValueType
。
在32位系统上,引用内存space只有4字节大;带有参考内存 space 我的意思是下面标记的框,例如 baz
或 bar
- 对于
ValueTypes
,这是存储值的地方;对于引用类型,这是存储 null
或对堆内存位置的引用的位置。
在32位系统上只有4个字节可用的情况下,16字节大的decimal
的值如何存储在堆栈中?
我的思路哪里错了?
我读了什么
- Memory in .NET - what goes where - 乔恩双向飞碟
- Arrays, heap and stack and value types - Whosebug
- Do value types (Integer, Decimal, Boolean, etc…) inherit from Object? - Whosebug
- 以及网上其他文章...
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.x
和 s.y
。将一个结构体入栈等于将结构体中的所有字段变量入栈.
又一更新:
另一件可能让您感到困惑的事情是,还有一种叫做 的另一种 临时存储 "registers" ,它也用于存储局部变量,并且真正地注册了只有四个字节长。 (除了那些是 8 的,但我们不要去那里。)一个 16 字节的结构如何存储在寄存器中? 不是。运行时根本不会将大结构放入寄存器。
问题
一个C#decimal
的值是局部变量的时候是存储在堆上吗?
我(相信)知道的
-
decimal
struct has 16 bytes. ValueType
类型的局部变量的值存储在栈中,decimal
继承自ValueType
。在32位系统上,引用内存space只有4字节大;带有参考内存 space 我的意思是下面标记的框,例如
baz
或bar
- 对于
ValueTypes
,这是存储值的地方;对于引用类型,这是存储null
或对堆内存位置的引用的位置。
在32位系统上只有4个字节可用的情况下,16字节大的decimal
的值如何存储在堆栈中?
我的思路哪里错了?
我读了什么
- Memory in .NET - what goes where - 乔恩双向飞碟
- Arrays, heap and stack and value types - Whosebug
- Do value types (Integer, Decimal, Boolean, etc…) inherit from Object? - Whosebug
- 以及网上其他文章...
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.x
和 s.y
。将一个结构体入栈等于将结构体中的所有字段变量入栈.
又一更新:
另一件可能让您感到困惑的事情是,还有一种叫做 的另一种 临时存储 "registers" ,它也用于存储局部变量,并且真正地注册了只有四个字节长。 (除了那些是 8 的,但我们不要去那里。)一个 16 字节的结构如何存储在寄存器中? 不是。运行时根本不会将大结构放入寄存器。