C#雖然可以使用指標,但如果是一般的方式
https://msdn.microsoft.com/zh-tw/library/f58wzh21.aspx
也就是搭配 fixed 陳述式 , 跟 C 指標操作存取相比會顯得非常沒彈性 , 所以在C#達不到C操作指標的靈活度.......但如果使用 Marshal 來進行 unmanaged 的記憶體配置拿到指標 , 則在C#中則"幾乎"(還有不少確認和爭議空間)可以達到 C 操作指標的靈活度
Marshal.AllocHGlobal
Marshal.FreeHGlobal
這兩的東西好用至極,之後要存取物件的習慣也幾乎跟C一樣,詳細的使用介紹就自行google,不多談.
這邊要說到的是有了這項能力後,處理模擬器其中一個問題顯然簡單而且有效率很多,電腦世界中雖然最基本的資料單位是 bits , 但硬體上資料能存取的最基本單元是 bytes , 8bit CPU 要模擬記憶體的硬體機本上宣告一個固定大小以byte為資料型態的array即可 , 不過到了32bit CPU一次存取可能就是 half-word (2bytes) 或是 word (4byte) , 有時候你從一個位址讀資料可能是要讀一個 byte , 有時候可能是一個 ushort , 有時候可能是一個 uint .
如果要讀4個byte, 你可以自己對 byte array 讀取4次 , 然後用 bitwise 的操作自己串成一個 uint ,顯然是麻煩 , 使用指標的狀況下 ,你可直接指定說我要從這指標的某個offset讀取 byte ushort uint 位元長度資料.
byte* bytepointer = (byte*)Marshal.AllocHGlobal(sizeof(byte) * 16);
bytepointer[0] = 0x00;
bytepointer[1] = 0x11;
bytepointer[2] = 0x22;
bytepointer[3] = 0x33;
bytepointer[4] = 0x44;
bytepointer[5] = 0x55;
bytepointer[6] = 0x66;
bytepointer[7] = 0x77;
bytepointer[8] = 0x88;
bytepointer[9] = 0x99;
bytepointer[10] = 0xaa;
bytepointer[11] = 0xbb;
bytepointer[12] = 0xcc;
bytepointer[13] = 0xdd;
bytepointer[14] = 0xee;
bytepointer[15] = 0xff;
ushort t_us;
t_us = ((ushort*) &bytepointer[4])[0];
Console.WriteLine(t_us.ToString("x4"));
t_us = ((ushort*)&bytepointer[9])[0];
Console.WriteLine(t_us.ToString("x4"));
uint t_ui;
t_ui = ((uint*)&bytepointer[2])[2];
Console.WriteLine(t_ui.ToString("x8"));
t_ui = ((uint*)&bytepointer[4])[1];
Console.WriteLine(t_ui.ToString("x8"));
t_ui = ((uint*)&bytepointer[9])[0];
Console.WriteLine(t_ui.ToString("x8"));
Marshal.FreeHGlobal((IntPtr)bytepointer);
資料存取變得像切豆腐一樣容易,對於資料長度讀取的轉換可以任意有彈性來做.
不管是Read 8/16/32 或是 Write 8/16/32 ,把資料長度型態改變, 對可以對應了.