32位和64位结构的大小

时间:2009-07-27 16:15:10

标签: .net architecture struct

.NET struct design guidelines中,它将结构的最大合理大小赋予16个字节。如何确定结构的大小,是否受程序运行架构的影响?这个值是32位还是两个拱?

3 个答案:

答案 0 :(得分:7)

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

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

然后,我发现无论如何我想写自己的结构是非常罕见的。你的情况怎么样?

答案 1 :(得分:4)

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

  • IntPtr的
  • UIntPtr

除非您的结构中直接或间接拥有其中一个,否则不应更改平台之间的大小。

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

  • 指针
  • 参考类型

所有这些类型虽然会以完全相同的方式改变。 32位平台上有4个字节,64位平台上有8个字节。

答案 2 :(得分:3)

是的,结构的大小受体系结构的影响。 32位的C#结构在4字节边界处对齐,在64位中它们是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

作为一个32位进程,我得到了这个输出:

[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个字节(int为4个字节,Uri为4个字节),64位为16个字节(int为4个字节,8个字节为引用Uri,我认为4个字节用于对齐)