瞭解下C# 不安全程式碼

大雄45發表於2022-07-31
導讀 當一個程式碼塊使用 unsafe 修飾符標記時,C# 允許在函式中使用指標變數。不安全程式碼或非託管程式碼是指使用了指標變數的程式碼塊。

瞭解下C# 不安全程式碼瞭解下C# 不安全程式碼

指標變數

指標 是值為另一個變數的地址的變數,即,記憶體位置的直接地址。就像其他變數或常量,您必須在使用指標儲存其他變數地址之前宣告指標。

指標變數宣告的一般形式為:

type* var-name;

下面是指標型別宣告的例項:

例項 描述
int* p p 是指向整數的指標。
double* p p 是指向雙精度數的指標。
float* p p 是指向浮點數的指標。
int** p p 是指向整數的指標的指標。
int*[] p p 是指向整數的指標的一維陣列。
char* p p 是指向字元的指標。
void* p p 是指向未知型別的指標。

在同一個宣告中宣告多個指標時,星號 * 僅與基礎型別一起寫入;而不是用作每個指標名稱的字首。 例如:

int* p1, p2, p3;     // 正確  
int *p1, *p2, *p3;   // 錯誤

下面的例項說明了 C# 中使用了 unsafe 修飾符時指標的使用:

例項

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: 99215364

您也可以不用宣告整個方法作為不安全程式碼,只需要宣告方法的一部分作為不安全程式碼。下面的例項說明了這點。

使用指標檢索資料值

您可以使用 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: 77128984
傳遞指標作為方法的引數

您可以向方法傳遞指標變數作為方法的引數。下面的例項說明了這點:

例項

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 *p 和 int[] p 是不同的型別。您可以增加指標變數 p,因為它在記憶體中不是固定的,但是陣列地址在記憶體中是固定的,所以您不能增加陣列 p。

因此,如果您需要使用指標變數訪問陣列資料,可以像我們通常在 C 或 C++ 中所做的那樣,使用 fixed 關鍵字來固定指標。

下面的例項演示了這點:

例項

using System;
namespace UnsafeCodeApplication
{
   class TestPointer
   {
      public unsafe static void Main()
      {
         int[]  list = {10, 100, 200};
         fixed(int *ptr = list)
         /* 顯示指標中陣列地址 */
         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,那麼您需要在專案屬性中啟用不安全程式碼。

步驟如下:

  1. 透過雙擊資源管理器(Solution Explorer)中的屬性(properties)節點,開啟專案屬性(project properties)。
  2. 點選 Build 標籤頁。
  3. 選擇選項"Allow unsafe code"。

原文來自:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2908330/,如需轉載,請註明出處,否則將追究法律責任。

相關文章