C# unsafe模式内存操作深入探索
生活随笔
收集整理的這篇文章主要介紹了
C# unsafe模式内存操作深入探索
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
C# unsafe模式內存操作深入探索
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks;namespace ConsoleApplication1 {class CTile{public CTileData _dat;public int x;}//結構體可能分配在堆上,也可能分配在棧上//1,結構體中無引用類型,則://a:若該結構體類型的變量X是類的內部成員,由于類是引用類型,則X分配在堆上//b:若非a的情況,則結構體分配在棧上unsafe struct CTileData//為了避開C#數組,因為它是一個引用類型。 {public int var1;public float var2;public fixed sbyte name[6]; //使用C++風格的定長數組,避免C#風格的引用數組public float var3;}//2,結構體中有引用類型,則該結構體類型的變量分配在堆上struct CTileData2{public int var1;public float var2;public string name;//有引用類型,結構體無論如何都分配在堆上了public float var3;}unsafe class Program{[DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]static extern void MemCopy(void* dest, void* src, int count);static void Main(string[] args){unsafe{var tile = new CTile();var dat = new CTileData();//棧上的結構體,可以直接取地址,堆上的則不行,因為堆上對象的地址是不定的(原因是內存管理)//同理,堆上的任何對象都不可直接取地址,必須使用fixed才行CTileData* ptd = &dat; var ms = new MemoryStream();var binWr = new BinaryWriter(ms, Encoding.ASCII);binWr.Write(10);binWr.Write(3.2f);binWr.Write("hello");//先寫入1字節長度(也就是說字符串長度最大256???),然后寫入hellobinWr.Write(109.9f);var bts = ms.GetBuffer();fixed (void* pbts = bts)//堆對象,必須使用fixed語法才能取地址 {var sz = sizeof(CTileData);MemCopy(ptd, pbts, sz);fixed (void* pt = &tile._dat)//堆上的結構體(堆對象),必須使用fixed語法才能取地址 {MemCopy(pt, pbts, sz);}}var v1 = ptd->var1; //10var v2 = ptd->var2; //3.2var strlen = *(ptd->name); //取一字節,字符串長度 5var straddr = ptd->name + 1; //跳過一字節,到達字符串起始地址string name = new string(straddr, 0, strlen); //hellovar v3 = ptd->var3; //這里數據不對,原因????//結論:C#真不適合做內存操作,若使用marshal,雖然方便了一些,但要經過一次內存申請和一次內存釋放,一次轉換到C#結構的過程,很蹩腳 }}} }?
posted on 2018-04-06 17:31 時空觀察者9號 閱讀(...) 評論(...) 編輯 收藏
總結
以上是生活随笔為你收集整理的C# unsafe模式内存操作深入探索的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++提高编译与链接速度的资料
- 下一篇: C# StopWatch的BUG????