c# 如何 使用共用體


用起來真的方便 轉摘如下:

C#借助FieldOffset屬性實現共用體與強制類型轉換

     這兩天被C#的強制類型轉換弄得有點不習慣。事出如此。

     在C#中,我打算讀二進制文。文件的結構很簡單,一連串的緊密存儲的int32值,以二進制方式存放。現在我希望隨機讀取第n個int32開始的i個值,並讀入到數組中。結果查一下C#只能讀到byte[]中,要不就是一個個讀出來循環放int[]。追求效率的我當然不希望這樣,如果能像C++那樣將byte[]強制轉換成int[]就好了。例如:

 

[cpp]  view plain  copy
 
 print?
  1. char tmp[64];       // 16個int。相當於C#的 byte[] tmp = new int[64];  
  2. int* dat;       // dat的指針。相當於C#的 int[] dat;  
  3. ifstream IF(...);   // 標准文件輸入流。相當於C#的 FileStream FS = new FileStream(...);  
  4. IF.read(tmp, 64);   // 讀取64個字節。  相當於C#的 FS.Read(tmp,0,64);  
  5. dat = (int*)tmp;    // 將tmp數組的首地址轉為int類型,則數組以4個字節為一個int轉換為int型的數組。  
  6.             // 數據在內存上沒有任何變化,因為數據本來就是int型的。  
  7.                         // 關鍵是這一步在C#中無法直接實現。  
  8. for (int i = 0; i < 16; i++)  
  9.     cout << dat[i] << " "; // 輸出數據。相當於C#的 Console.Write(dat[i]+" ");  

在C#中無法直接實現,為此我想了好些辦法,也查了好久,直到我見到了這樣的代碼:

 

[csharp]  view plain  copy
 
 print?
  1. using System;  
  2. using System.IO;  
  3. using System.Collections.Generic;  
  4. using System.Linq;  
  5. using System.Text;  
  6. // 提供各種各樣支持 COM 互操作 及平台調用服務的成員  
  7. using System.Runtime.InteropServices;  
  8.   
  9. namespace test  
  10. {  
  11.     class Program  
  12.     {  
  13.         // StructLayout使設計者可以控制類或結構的數據字段的物理布局  
  14.         // Explicit與FieldOffset一起可以控制每個數據成員的精確位置  
  15.         [StructLayout(LayoutKind.Explicit)]  
  16.         public struct S1  
  17.         {  
  18.             // FieldOffset控制字段所在的物理位置偏移為0  
  19.             [FieldOffset(0)]  
  20.             public byte[] a;  
  21.             // 同樣偏移為0,開始位置與a重疊了。  
  22.             [FieldOffset(0)]  
  23.             public int[] b;  
  24.         }  
  25.   
  26.         static void Main(string[] args)  
  27.         {  
  28.             S1 s = new S1(); // 要new,不然b會報“使用了可能未賦值的字段”  
  29.             s.a=new byte[64];  
  30.   
  31.             FileStream FS = new FileStream("E:\\test.txt", FileMode.Open);  
  32.             // 以s.a來接收文件的數據  
  33.             FS.Read(s.a,0,64);  
  34.   
  35.             // 自己保證讀b的時候不要越界  
  36.             for (int i = 0; i < 16; i++)   
  37.                 Console.Write(s.b[i]+" "); // 以b來使用數據  
  38.   
  39.             Console.ReadKey();  
  40.         }  
  41.     }  
  42. }  

 

原理實際上跟C++一樣,將一個int[]型的變量指向與byte[]型變量相同的內存區域,跟C++中將dat指向char數組的首地址是一樣的。同樣,這樣的結構體功能與C++的共用體是一樣的,即一個結構可以作為多種數據類型,而具體是什么類型視情況而定。

測試所使用的文件就不上傳了,有WinHex的可以自己編輯一個,沒有的也可以寫程序將從0xF到0x0的16個數以二進制方式輸出到文件中。文件的內容用WinHex打開以16進制顯示應該如下:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM