關於.net託管環境下struct類型的記憶體布局的認識

來源:互聯網
上載者:User

熟悉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

《完》

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.