.net 32位和64位上的结构大小

.net 32位和64位上的结构大小,.net,architecture,struct,.net,Architecture,Struct,在中,它给出了结构的最大合理大小为16字节。如何确定结构的大小,以及它是否受运行程序的体系结构的影响?这个值是32位的,还是两个拱门都有?这不是一个硬性的值——它只是一个指南,一个经验法则。根据具体情况,24字节甚至32字节仍然是完全合理的-但是如果你的结构变得那么大,你应该首先问问自己它是否适合作为一个结构。在这种情况下,在执行赋值或将参数传递给方法(etc)的任何时候复制这32个字节可能是正确的做法;在其他情况下,您应该真正使用类 至于如何确定结构有多大,通常这很明显,因为通常一个值类型只包

在中,它给出了结构的最大合理大小为16字节。如何确定结构的大小,以及它是否受运行程序的体系结构的影响?这个值是32位的,还是两个拱门都有?

这不是一个硬性的值——它只是一个指南,一个经验法则。根据具体情况,24字节甚至32字节仍然是完全合理的-但是如果你的结构变得那么大,你应该首先问问自己它是否适合作为一个结构。在这种情况下,在执行赋值或将参数传递给方法(etc)的任何时候复制这32个字节可能是正确的做法;在其他情况下,您应该真正使用类

至于如何确定结构有多大,通常这很明显,因为通常一个值类型只包含其他值类型。如果您的结构包含引用(或
IntPtr
/
UIntPtr
),那么这是一个更大的问题,但这种情况非常罕见。(正如Mehrdad指出的,为了对齐,还存在填充的问题。)


然后,我再次发现,无论如何我都很少想编写自己的结构。您的情况如何?

在.Net中,大多数类型在32位和64位程序之间不会改变大小。框架定义的唯一两种值类型将根据平台改变其大小,它们是

  • IntPtr
  • UIntPtr
除非在结构中直接或间接地包含其中一个,否则它不应在不同平台之间更改大小

正如Mehrdad指出的,其他两类字段将根据平台改变大小

  • 指针
  • 参考类型

然而,所有这些类型都将以完全相同的方式发生变化。32位平台上为4字节,64位平台上为8字节。

是的,结构的大小受体系结构的影响。32位的C#结构在4字节边界上对齐,64位的C#结构在8字节边界上对齐

例如:

struct Foo
{
   int bar;
}
此结构的实例在32位进程中占用4个字节,在64位进程中占用8个字节,即使“int bar”在32位和64位进程中仅占用4个字节

更新:

我用这个做了一些测试。我写了这段代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    struct Bar
    {
        int a;
    }

    struct Foo
    {
        Uri uri;
        int a;
    }

    class Program
    {
        static void Main(string[] args)
        {
            Foo[] foo;
            long fooBefore = System.GC.GetTotalMemory(true);
            foo = new Foo[10];
            long fooAfter = System.GC.GetTotalMemory(true);

            Bar[] bar;
            long barBefore = System.GC.GetTotalMemory(true);
            bar = new Bar[10];
            long barAfter = System.GC.GetTotalMemory(true);

            Foo aFoo = new Foo();
            Bar aBar = new Bar();

            System.Console.Out.WriteLine(String.Format("[Foo] Size of array of 10: {0}, Marshal size of one: {1}", fooAfter - fooBefore, System.Runtime.InteropServices.Marshal.SizeOf(aFoo)));
            System.Console.Out.WriteLine(String.Format("[Bar] Size of array of 10: {0}, Marshal size of one: {1}", barAfter - barBefore, System.Runtime.InteropServices.Marshal.SizeOf(aBar)));
            System.Console.ReadKey();
        }
    }
}
作为64位进程,我得到以下输出:

[Foo] Size of array of 10: 208, Marshal size of one: 16
[Bar] Size of array of 10: 88, Marshal size of one: 4
[Foo] Size of array of 10: 92, Marshal size of one: 8
[Bar] Size of array of 10: 64, Marshal size of one: 4
作为32位进程,我得到以下输出:

[Foo] Size of array of 10: 208, Marshal size of one: 16
[Bar] Size of array of 10: 88, Marshal size of one: 4
[Foo] Size of array of 10: 92, Marshal size of one: 8
[Bar] Size of array of 10: 64, Marshal size of one: 4
意见:

  • 简单结构Bar在32位和64位进程上似乎都需要4个字节
  • 另一个结构Foo似乎在32位上使用了8个字节(4个字节表示int,4个字节表示对Uri的引用),但在64位上使用了16个字节(4个字节表示int,8个字节表示对Uri的引用,我认为4个字节表示对齐)

JaredPar似乎不同意——你知道从哪里可以获得信息吗?嗯,也许我搞错了。我会进一步调查的。