標籤:col 原理 font 上傳 c# 支援 .text 實現 輸入
用起來真的方便 轉摘如下:
C#藉助FieldOffset屬性實現共用體與強制類型轉換
這兩天被C#的強制類型轉換弄得有點不習慣。事出如此。
在C#中,我打算讀二進位文。檔案的結構很簡單,一連串的緊密儲存的int32值,以二進位方式存放。現在我希望隨機讀取第n個int32開始的i個值,並讀入到數組中。結果查一下C#只能讀到byte[]中,要不就是一個個讀出來迴圈放int[]。追求效率的我當然不希望這樣,如果能像C++那樣將byte[]強制轉換成int[]就好了。例如:
[cpp] view plain copy print?
- char tmp[64]; // 16個int。相當於C#的 byte[] tmp = new int[64];
- int* dat; // dat的指標。相當於C#的 int[] dat;
- ifstream IF(...); // 標準檔案輸入資料流。相當於C#的 FileStream FS = new FileStream(...);
- IF.read(tmp, 64); // 讀取64個位元組。 相當於C#的 FS.Read(tmp,0,64);
- dat = (int*)tmp; // 將tmp數組的首地址轉為int類型,則數組以4個位元組為一個int轉換為int型的數組。
- // 資料在記憶體上沒有任何變化,因為資料本來就是int型的。
- // 關鍵是這一步在C#中無法直接實現。
- for (int i = 0; i < 16; i++)
- cout << dat[i] << " "; // 輸出資料。相當於C#的 Console.Write(dat[i]+" ");
在C#中無法直接實現,為此我想了好些辦法,也查了好久,直到我見到了這樣的代碼:
[csharp] view plain copy print?
- using System;
- using System.IO;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- // 提供各種各樣支援 COM 互操作 及平台叫用服務的成員
- using System.Runtime.InteropServices;
-
- namespace test
- {
- class Program
- {
- // StructLayout使設計者可以控制類或結構的資料欄位的物理布局
- // Explicit與FieldOffset一起可以控制每個資料成員的精確位置
- [StructLayout(LayoutKind.Explicit)]
- public struct S1
- {
- // FieldOffset控制欄位所在的物理位置位移為0
- [FieldOffset(0)]
- public byte[] a;
- // 同樣位移為0,開始位置與a重疊了。
- [FieldOffset(0)]
- public int[] b;
- }
-
- static void Main(string[] args)
- {
- S1 s = new S1(); // 要new,不然b會報“使用了可能未賦值的欄位”
- s.a=new byte[64];
-
- FileStream FS = new FileStream("E:\\test.txt", FileMode.Open);
- // 以s.a來接收檔案的資料
- FS.Read(s.a,0,64);
-
- // 自己保證讀b的時候不要越界
- for (int i = 0; i < 16; i++)
- Console.Write(s.b[i]+" "); // 以b來使用資料
-
- Console.ReadKey();
- }
- }
- }
原理實際上跟C++一樣,將一個int[]型的變數指向與byte[]型變數相同的記憶體地區,跟C++中將dat指向char數組的首地址是一樣的。同樣,這樣的結構體功能與C++的共用體是一樣的,即一個結構可以作為多種資料類型,而具體是什麼類型視情況而定。
測試所使用的檔案就不上傳了,有WinHex的可以自己編輯一個,沒有的也可以寫程式將從0xF到0x0的16個數以二進位方式輸出到檔案中。檔案的內容用WinHex開啟以16進位顯示應該如下:
c# 如何 使用共用體