C#不安全代碼

C# 允許在代碼塊的函數中使用指針變量來標記不安全的修飾符。不安全代碼或非託管代碼是使用指針變量的代碼塊。

指針

指針是一個變量,其值是另一個變量的地址,即存儲器位置的直接地址。 類似於任何變量或常量,要使用指針必須先聲明指針,然後才能使用它來存儲任何變量地址。

指針聲明的一般形式是:

type *var-name;

以下是有效的指針聲明:

int    *ip;    /* pointer to an integer */
double *dp;    /* pointer to a double */
float  *fp;    /* pointer to a float */
char   *ch     /* pointer to a character */

以下示例說明如何在 C# 中使用指針,使用不安全的修飾符:

using System;
namespace UnsafeCodeApplication
{
   class Program
   {
      static unsafe void Main(string[] args)
      {
         int var = 20;
         int* p = &var;
         Console.WriteLine("Data is: {0} ",  var);
         Console.WriteLine("Address is: {0}",  (int)p);
         Console.ReadKey();
      }
   }
}

當上述代碼通過編譯並執行後,會產生以下結果:

Data is: 20
Address is: 890153869

不必將整個方法聲明爲不安全,也可將代碼的一部分聲明爲不安全。下一節中的示例顯示了這一點。

使用指針檢索數據值

可以使用ToString()方法檢索由指針變量引用的位置處存儲的數據。以下示例演示如下:

using System;
namespace UnsafeCodeApplication
{
   class Program
   {
      public static void Main()
      {
         unsafe
         {
            int var = 20;
            int* p = &var;
            Console.WriteLine("Data is: {0} " , var);
            Console.WriteLine("Data is: {0} " , p->ToString());
            Console.WriteLine("Address is: {0} " , (int)p);
         }

         Console.ReadKey();
      }
   }
}

當編譯和執行上述代碼時,會產生以下結果:

Data is: 20
Data is: 20
Address is: 97122341

將指針作爲參數傳遞給方法

可以將指針變量傳遞給方法作爲參數。以下示例說明了這一點:

using System;
namespace UnsafeCodeApplication
{
   class TestPointer
   {
      public unsafe void swap(int* p, int *q)
      {
         int temp = *p;
         *p = *q;
         *q = temp;
      }

      public unsafe static void Main()
      {
         TestPointer p = new TestPointer();
         int var1 = 10;
         int var2 = 20;
         int* x = &var1;
         int* y = &var2;

         Console.WriteLine("Before Swap: var1:{0}, var2: {1}", var1, var2);
         p.swap(x, y);

         Console.WriteLine("After Swap: var1:{0}, var2: {1}", var1, var2);
         Console.ReadKey();
      }
   }
}

當上述代碼被編譯並執行時,它產生以下結果:

Before Swap: var1: 10, var2: 20
After Swap: var1: 20, var2: 10

使用指針訪問數組元素

在 C# 中,一個數組名稱和一個與數組數據類型相同的數據類型的指針是不一樣的變量類型。 例如,int * pint [] p是兩個不一樣的類型。我們可以增加指針變量p,因爲它在內存中不是固定的,而數組的地址是固定在內存中,所以不能增加。

因此,如果您需要使用指針變量來訪問數組數據,如傳統上在C語言或C++(請查閱:C指針)中所做的那樣,則需要使用fixed關鍵字修復指針。

以下示例演示如下:

using System;
namespace UnsafeCodeApplication
{
   class TestPointer
   {
      public unsafe static void Main()
      {
         int[]  list = {10, 100, 200};
         fixed(int *ptr = list)

         /* let us have array address in pointer */
         for ( int i = 0; i < 3; i++)
         {
            Console.WriteLine("Address of list[{0}]={1}",i,(int)(ptr + i));
            Console.WriteLine("Value of list[{0}]={1}", i, *(ptr + i));
         }

         Console.ReadKey();
      }
   }
}

當編譯和執行上述代碼時,會產生以下結果:

Address of list[0] = 31627168
Value of list[0] = 10
Address of list[1] = 31627172
Value of list[1] = 100
Address of list[2] = 31627176
Value of list[2] = 200

編譯不安全的代碼

要編譯不安全的代碼,必須使用命令行編譯器指定/unsafe命令行開關。

例如,要編譯一個名稱爲prog1.cs的源代碼中包含不安全代碼,請從命令行中輸入命令:

csc /unsafe prog1.cs

如果您使用的是Visual Studio IDE,則需要在項目屬性中啓用不安全的代碼。

參考以下步驟:

  • 通過雙擊解決方案資源管理器中的屬性節點打開項目屬性(project properties)。
  • 單擊構建(Build)選項卡。
  • 選擇「允許不安全代碼(Allow unsafe code)」選項。