.Net / C#:整数的实际大小是多少?

时间:2009-03-01 21:48:16

标签: c# integer

在.Net中,整数是值类型,这意味着它存储在堆栈中。 整数也是类(通常是System.Int32)。他们有像CompareTo,Equals,......这样的方法,它们应该在堆栈上占用超过四个字节。 下面的例子显示它们只占用4个字节:

unsafe static void Main()
{
    int a = 2, b = 4;
    Console.WriteLine("Adress of a : {0}", (int)&a);
    Console.WriteLine("Adress of b : {0}", (int)&b);
    Console.WriteLine("Size of integer: {0}", (int)(&a) - (int)(&b));
}

输出:

Adress of a : 1372876
Adress of b : 1372872
Size of integer: 4

CLR是否对整数和其他值类型(float,long,double,...)进行特殊处理?

4 个答案:

答案 0 :(得分:15)

不,它们是值类型的事实并不意味着它们存储在堆栈中。这意味着它们已存储wherever the variable lives

但是,嘿,让我们推动本地变量业务,此时(没有捕获等)他们在堆栈上生存。它们需要4个字节。为什么他们需要更多?堆栈上不需要vtable,因为元数据已经指定了类型:对于将调用哪些虚拟方法等没有歧义。

编辑:正如Shawn的评论所指出的那样(但我想让它更明显),System.Int32是一个结构,而不是一个类。 (实际上CLR会创建一个阴影引用类型来覆盖整数的盒装值,但这是另一回事。)

答案 1 :(得分:5)

  

因此,它们应该在堆栈上占用超过四个字节。

这不遵循。编译器运行时知道确切的类型。值类型不能进一步子类型化,因此不需要“vtable”或其他特定于对象的动态调度机制。

当值类型被装箱以将它们放在堆上时,需要正常的.NET Object头。

答案 2 :(得分:4)

如果值类型是方法中的局部变量,则在堆栈上分配值类型。如果值类型是类的成员,它将被分配为堆上对象的内存区域的一部分。

值类型变量不需要任何额外的数据来跟踪类型,就像引用类型一样。编译器总是知道值类型变量的位置以及它们的类型,因此除了实际数据之外不需要额外的数据。 Int32变量总是四个字节。

在堆上分配引用类型,它具有指向它的引用(或更多)。引用本身实际上是一个值类型,因此它只是一个指针,编译器会跟踪它的位置以及它的类型。引用的类型不必与它指向的对象的类型相同,因此对象需要额外的信息来跟踪类型。例如,指向StringBuilder类的实例的对象引用:

object o = new StringBuilder();

这里编译器跟踪引用的类型是对象,因此它只是一个指针(32位应用程序中的4个字节)。 StringBuilder对象存储在堆上,它有两个额外的指针,用于跟踪实际类型。

值类型也可以加框,即存储为堆上的对象。将值类型转换为Object:

时会发生这种情况
object p = 42;

这将在堆上分配一个对象并将整数的值复制到其中。此对象需要额外的类型信息来跟踪类型,因此它将在堆上使用12个字节而不是4个(在32位应用程序中)。

答案 3 :(得分:0)

类型定义与为该类型的实例存储的值之间存在差异,例如......

// type definition
public class Bla {}
// instance of type bla
public Bla myBla = new Bla();

本质上int的大小就像它看起来的那样(4个字节),但正如你所知,这是它需要声明的内存空间的大小。

类型定义存储在别处,像CompareTo这样的方法只会以这种方式声明,而不是为你声明的那个类型的每个实例声明一次,因为它们作为框架库本身的一部分加载,用于你的应用程序,这些定义有效地占用了0个空间。

相关问题