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

发布于 2024-07-14 21:32:40 字数 559 浏览 3 评论 0原文

在.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 是否对整数和其他值类型(浮点型、长整型、双精度型……)进行特殊处理?

in .Net, integers are valuetypes, which means it stored on the stack.
Integers are also class (System.Int32 usually). They have methods like CompareTo, Equals,...Thus, they should take more than four bytes on the stack.
The example below show however that they take exactly 4 bytes:

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));
}

Output:

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

Does the CLR make a special treatment for integer and other valuetypes (float, long, double,...)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

野生奥特曼 2024-07-21 21:32:40

不,它们是值类型这一事实并不意味着它们存储在堆栈中。 这意味着它们存储在变量所在的位置

但是,嘿,让我们来讨论局部变量业务,此时(没有捕获等)它们确实存在于堆栈中。 它们占用 4 个字节。 他们为什么要拿更多? 堆栈上不需要 vtable,因为元数据已经指定了类型:对于将调用哪些虚拟方法等没有任何歧义。

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

No, the fact that they're value types doesn't mean they're stored on the stack. It means they're stored wherever the variable lives.

But hey, let's roll with the local variable business, at which point (with no captures etc) they do live on the stack. And they take 4 bytes. Why would they take more? There's no need for a vtable on the stack, because the metadata already specifies the type: there's no ambiguity as to what virtual methods will be called etc.

EDIT: As pointed out in a comment by Shawn (but I wanted to make it more obvious), System.Int32 is a structure, not a class. (In fact the CLR will create a shadow reference type to cover boxed values of ints, but that's a different matter.)

能否归途做我良人 2024-07-21 21:32:40

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

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

当对值类型进行装箱以将其放入堆时,需要普通的 .NET 对象标头。

Thus, they should take more than four bytes on the stack.

This does not follow. The compiler and runtime knows the exact type. Value types cannot be further subtyped, so no need for "vtable" or other object specific dynamic dispatch mechanism.

When value types are boxed to put them on the heap, the normal .NET Object header is needed.

挽心 2024-07-21 21:32:40

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

与引用类型不同,值类型变量不需要任何额外的数据来跟踪类型。 编译器总是知道值类型变量在哪里以及它们的类型是什么,因此除了实际数据之外不需要额外的数据。 Int32 变量始终为四个字节。

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

object o = new StringBuilder();

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

值类型也可以装箱,即作为对象存储在堆上。 当您将值类型转换为对象时,会发生这种情况:

object p = 42;

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

A value type is allocated on the stack if it's a local variable in a method. If a value type is a member of a class, it will be allocated as part of the object's memory area on the heap.

A value type variable does not need any extra data to keep track of the type, as reference types does. The compiler always knows where the value type variables are and what their type is, so there is no extra data needed in addition to the actual data. An Int32 variable will always be four bytes.

A reference type is allocated on the heap, and it has a reference (or more) that points to it. The reference itself is actually a value type, so it will just be a pointer, the compiler keeps track of where it is and what type it is. The type of the reference doesn't have to be the same as the type of the object that it is pointing to, so the object needs extra information to keep track of the type. For example, an object reference pointing to an instance of the StringBuilder class:

object o = new StringBuilder();

Here the compiler keeps track of that type of the reference is object, so it will just be a pointer (4 bytes in a 32-bit application). The StringBuilder object is stored on the heap, and it has two extra pointers with it that keeps track of the actual type.

A value type can also be boxed, i.e. stored as an object on the heap. This occurs when you cast a value type to Object:

object p = 42;

This will allocate an object on the heap and copy the value of the integer into it. This object will need the extra type information to keep track of the type, so it will use 12 bytes on the heap instead of four (in a 32 bit application).

初懵 2024-07-21 21:32:40

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

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

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

类型定义存储在其他地方,像 CompareTo 这样的方法仅以这种方式声明一次,而不是为您声明的该类型的每个实例声明一次,并且由于它们作为框架库本身的一部分加载,出于应用程序的目的,这些定义实际上占用 0 空间。

There's a difference between the type definition and the value stored for an instance of that type for example ...

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

essentially the size of an int is as it seems (4 bytes) but as you figured out, that's the size of the memory space it requires to declare.

The type definition is stored elsewhere, methods like CompareTo are only declared once this way instead of once for each instance of that type you declare, and since they are loaded as part of the framework libraries itself, for the purpose of your application, these definitions effectively do take up 0 space.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文