无涯教程-C# - 不安全代码

58 阅读3分钟

指针是一个变量,其值是另一个变量的地址,即存储器位置的直接地址。与任何变量或常量类似,必须先声明指针,然后才能使用它存储任何变量地址。

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;

     </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Data is: {0} "</span><span class="pun">,</span><span class="pln">  </span><span class="kwd">var</span><span class="pun">);</span><span class="pln">
     </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Address is: {0}"</span><span class="pun">,</span><span class="pln">  </span><span class="pun">(</span><span class="kwd">int</span><span class="pun">)</span><span class="pln">p</span><span class="pun">);</span><span class="pln">
     </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadKey</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

} }

当编译并执行上述代码时,它将生成以下输出-

Data is: 20
Address is: 99215364

您也可以将代码的一部分声明为不安全,而不是将整个方法声明为不安全。

指针检索数据值

可以使用ToString()方法检索存储在指针变量引用的位置处的数据。

using System;

namespace UnsafeCodeApplication { class Program { public static void Main() { unsafe { int var = 20; int* p = &var;

        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Data is: {0} "</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="kwd">var</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Data is: {0} "</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> p</span><span class="pun">-&gt;</span><span class="typ">ToString</span><span class="pun">());</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Address is: {0} "</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pun">)</span><span class="pln">p</span><span class="pun">);</span><span class="pln">
     </span><span class="pun">}</span><span class="pln">
     </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadKey</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

} }

当编译并执行上述代码时,它将生成以下输出-

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;

     </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Before Swap: var1:{0}, var2: {1}"</span><span class="pun">,</span><span class="pln"> var1</span><span class="pun">,</span><span class="pln"> var2</span><span class="pun">);</span><span class="pln">
     p</span><span class="pun">.</span><span class="pln">swap</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">

     </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"After Swap: var1:{0}, var2: {1}"</span><span class="pun">,</span><span class="pln"> var1</span><span class="pun">,</span><span class="pln"> var2</span><span class="pun">);</span><span class="pln">
     </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadKey</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

} }

编译并执行上述代码时,将生成以下输出-

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

指针访问数组

在C#中,数组名称和指向与数组数据相同的数据类型的指针不是相同的变量类型。例如,int*p和int[]p不是同一类型。可以递增指针变量p,因为它在内存中不固定,但数组地址在内存中是固定的,并且不能递增。

using System;

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

     </span><span class="com">/* let us have array address in pointer */</span><span class="pln">
     </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Address of list[{0}]={1}"</span><span class="pun">,</span><span class="pln">i</span><span class="pun">,(</span><span class="kwd">int</span><span class="pun">)(</span><span class="pln">ptr </span><span class="pun">+</span><span class="pln"> i</span><span class="pun">));</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Value of list[{0}]={1}"</span><span class="pun">,</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> </span><span class="pun">*(</span><span class="pln">ptr </span><span class="pun">+</span><span class="pln"> i</span><span class="pun">));</span><span class="pln">
     </span><span class="pun">}</span><span class="pln">
     
     </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadKey</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

} }

当编译并执行上述代码时,它将生成以下输出-

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命令。

例如,要编译一个名为program 1.cs的程序,其中包含不安全的代码,请从命令行给出命令-

csc /unsafe prog1.cs

如果使用的是Visual Studio IDE,则需要在元素属性中启用不安全代码的使用。

要做到这一点,-

  • 通过双击"Solution Explorer"中的"properties"节点打开元素属性。

  • 单击Build tab。

  • 选择选项 "Allow unsafe code".

参考链接

www.learnfk.com/csharp/csha…