鍍金池/ 教程/ C#/ C#不安全代碼
C#屬性(Properties)
C#與Java比較
C#方法
C#枚舉
C#關(guān)鍵字
C# StreamReader類(lèi)
C#不安全代碼
C#文件(I/O)
C#匿名方法
C#線程同步
C# Thread類(lèi)
C#主線程
C#數(shù)據(jù)類(lèi)型
C# FileStream類(lèi)
C#預(yù)處理指令
C#繼承
C#循環(huán)
C#決策結(jié)構(gòu)
C#集合
C#反射
C#類(lèi)型轉(zhuǎn)換
C#泛型
C# StringReader類(lèi)
C#歷史
C#運(yùn)算符重載
C#屬性
C#線程實(shí)例:Sleep()方法
C#線程示例:優(yōu)先級(jí)
C#線程實(shí)例:Join()方法
C# BinaryReader類(lèi)
C#類(lèi)
C#索引器
C# BinaryWriter類(lèi)
C#序列化
C#常量和文字
C#程序結(jié)構(gòu)
C#封裝
C#事件
C#可空類(lèi)型(nullable)
C#基本語(yǔ)法
C#異常處理
C#教程
C#接口
C# System.IO命名空間
C#線程命名實(shí)例
C# StringWriter類(lèi)
C#線程實(shí)例
C#數(shù)組
C#正則表達(dá)式
C#命名空間
C#反序列化
C#與C++比較
C# TextWriter類(lèi)
C#多線程
C#字符串
C#是什么?
C#變量
C# FileInfo類(lèi)
C#線程實(shí)例:Abort()方法
C#結(jié)構(gòu)體
C#運(yùn)算符
C#入門(mén)程序
C#多線程生命周期
C# TextReader類(lèi)
C# DirectoryInfo類(lèi)
C#委托

C#不安全代碼

C# 允許在代碼塊的函數(shù)中使用指針變量來(lái)標(biāo)記不安全的修飾符。不安全代碼或非托管代碼是使用指針變量的代碼塊。

指針

指針是一個(gè)變量,其值是另一個(gè)變量的地址,即存儲(chǔ)器位置的直接地址。 類(lèi)似于任何變量或常量,要使用指針必須先聲明指針,然后才能使用它來(lái)存儲(chǔ)任何變量地址。

指針聲明的一般形式是:

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 */

以下示例說(shuō)明如何在 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();
      }
   }
}

當(dāng)上述代碼通過(guò)編譯并執(zhí)行后,會(huì)產(chǎn)生以下結(jié)果:

Data is: 20
Address is: 890153869

不必將整個(gè)方法聲明為不安全,也可將代碼的一部分聲明為不安全。下一節(jié)中的示例顯示了這一點(diǎn)。

使用指針檢索數(shù)據(jù)值

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

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();
      }
   }
}

當(dāng)編譯和執(zhí)行上述代碼時(shí),會(huì)產(chǎn)生以下結(jié)果:

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

將指針作為參數(shù)傳遞給方法

可以將指針變量傳遞給方法作為參數(shù)。以下示例說(shuō)明了這一點(diǎn):

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();
      }
   }
}

當(dāng)上述代碼被編譯并執(zhí)行時(shí),它產(chǎn)生以下結(jié)果:

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

使用指針訪問(wèn)數(shù)組元素

在 C# 中,一個(gè)數(shù)組名稱(chēng)和一個(gè)與數(shù)組數(shù)據(jù)類(lèi)型相同的數(shù)據(jù)類(lèi)型的指針是不一樣的變量類(lèi)型。 例如,int * pint [] p是兩個(gè)不一樣的類(lèi)型。我們可以增加指針變量p,因?yàn)樗趦?nèi)存中不是固定的,而數(shù)組的地址是固定在內(nèi)存中,所以不能增加。

因此,如果您需要使用指針變量來(lái)訪問(wèn)數(shù)組數(shù)據(jù),如傳統(tǒng)上在C語(yǔ)言或C++(請(qǐng)查閱:C指針)中所做的那樣,則需要使用fixed關(guān)鍵字修復(fù)指針。

以下示例演示如下:

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();
      }
   }
}

當(dāng)編譯和執(zhí)行上述代碼時(shí),會(huì)產(chǎn)生以下結(jié)果:

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命令行開(kāi)關(guān)。

例如,要編譯一個(gè)名稱(chēng)為prog1.cs的源代碼中包含不安全代碼,請(qǐng)從命令行中輸入命令:

csc /unsafe prog1.cs

如果您使用的是Visual Studio IDE,則需要在項(xiàng)目屬性中啟用不安全的代碼。

參考以下步驟:

  • 通過(guò)雙擊解決方案資源管理器中的屬性節(jié)點(diǎn)打開(kāi)項(xiàng)目屬性(project properties)。
  • 單擊構(gòu)建(Build)選項(xiàng)卡。
  • 選擇“允許不安全代碼(Allow unsafe code)”選項(xiàng)。

上一篇:C# Thread類(lèi)下一篇:C#委托