关于.net托管环境下struct类型的内存布局的认识

熟悉C/C++的朋友都知道,struct类型中的成员在内存中都是按顺序依次存放的,即按成员的声明顺序,并且通常是按成员中占用空间最大的成员进行对齐的。

然 而,到了.net托管环境中,则有所不同。CLR为我们提供了两种不同的结构成员内存布局方式:LayoutKind.Sequential和 LayoutKind.Explicit,分别实现常用的顺序布局和按偏移量精确布局。前者是CLR的默认值。我们可以在声明struct时加上修饰: [StructLayout(LayoutKind.Sequential)]来告诉CLR要采用的内存布局方式为顺序。采用这种布局方式声明的 struct在内存中和非托管环境中声明的struct一致,所以,通常在和非托管Dll进行交互调用的时候,应将struct声明成顺序式的。看下面的 示例:

[StructLayout(LayoutKind.Sequential)]
struct S1 //16byte
{
    int i; //4byte
    double b; //8byte
}

按 顺序布局的S1本来只占用了12个byte的内存空间,但是,当我们用sizeof(S1)测试的时候,发现它竟然占用了16个byte的空间,这是因为 LayoutKind.Sequential(默认)情况下,CLR对struct的Layout的处理方法与C/C++中默认的处理方式相同,即按照结 构中占用空间最大的成员进行对齐(Align)。显然,这种方式浪费了一定的内存空间。

然而,按偏移量来布局的方式也有一定的不足,当偏移量计算不准的时候,就会造成数据丢失。请看下面的示例:

[StructLayout(LayoutKind.Explicit)]
struct S2
{
     [FieldOffset(0)] int i;
     [FieldOffset(0)] double b;
}

S2中两个成员的内存位置偏移量都是0,这就意味着它们占用了相同的部分内存空间。当修改其中一个的值时,必然导致另一个的值也发生变化。因为,偏移量的计算应当非常小心才是。以下是一段来MSND上的比较好的例子:

using System.Runtime.InteropServices ;   
[StructLayout(LayoutKind.Explicit, Size=16, CharSet=CharSet.Ansi)]
public class MySystemTime
{
[FieldOffset(0)]public ushort wYear;
[FieldOffset(2)]public ushort wMonth;
[FieldOffset(4)]public ushort wDayOfWeek;
[FieldOffset(6)]public ushort wDay;
[FieldOffset(8)]public ushort wHour;
[FieldOffset(10)]public ushort wMinute;
[FieldOffset(12)]public ushort wSecond;
[FieldOffset(14)]public ushort wMilliseconds;
}
细心的朋友可能发现:代码中用的是class面不是struct,这说明class和struct其实没有本质的区别。再看一个使用顺序方式的比较好的例子:

      [StructLayout(LayoutKind.Sequential)]
      public   struct   POINT   {
            public   POINT(int   xx,   int   yy)   {   x=xx;   y=yy;   } //构造函数
            public   int   x;
            public   int   y;
            public   override   string   ToString()   {
                  String   s   =   String.Format( "({0},{1}) ",   x,   y);
                  return   s;
            }
      }

补充说明:

其实,.net中还有第三种布局方式:[StructLayout(LayoutKind.Auto)]。这种方式下,CLR会对结构体中 的字段顺序进行调整使之占用尽可能少的内存,也就是说,CLR会自动将struct中占用空间多的排在前面,占用空间少的排在后面,并进行4byte的内 存对齐,这样下来,可以相比顺序方式节省一定的内存,但还是比精确定义偏移量的方式多浪费一些内存。

有关.net托管环境下struct类型的内存布局的问题,更多信息可以阅读网友happyhippy的博文:
http://www.cnblogs.com/happyhippy/archive/2007/04/12/710927.aspx

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12639172/viewspace-624903/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/12639172/viewspace-624903/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值