您的位置:首页 > 编程语言 > C#

C#的不安全代码和指针

2017-07-07 15:20 253 查看
coffeecato写在前面:

本文来自《果壳中的C# C#5.0权威指南》 第四章 C#高级特性 4.14不安全代码和指针。由于C#中对于指针的使用有诸多不便,翻到了上面这本书,特别介绍了unsafe及fixed关键字的使用。这里做一摘录,方便日后查阅。

不安全代码和指针

C#支持通过标记为不安全和使用/unsafe编译器选项编译的代码块中的指针直接进行内存操作。指针类型主要用来与C语言API进行互操作,但是也可以用来访问托管堆以外的内存,或者分析严重影响性能的热点。

指针基础

对于每一种数值类型或指针类型V,它们都有对应的指针类型V*。指针实例保存了值的地址。这可以认为是类型V,但是指针类型可以(不安全地)转换到其他任意指针类型。主要的指针运算符有:

运算符作用
&取地址运算符返回指向某个值的地址的指针
*引用运算符返回指针地址所指的值
->指向成员的指针运算符是一个快捷语法,其中x->y等同于(*x).y
不安全代码

使用unsafe关键字标记一个类型、类型成员或语句块,就可以在该范围内使用指针类型和对内存执行C++中的指针操作。下面的例子使用指针实现一个位图的快速处理:

unsafe void BlueFilter(int[,] bitmap)
{
int length = bitmap.Length;
fixed(int* b = bitmap)
{
int* p = b;
for (int i = 0; i < length; i++)
*p++ &= 0xFF;
}
}


不安全代码与对应的安全实现相比运行速度更快。在这个例子中,代码需要使用一个遍历数组索引和检查边界的嵌套循环。一个不安全的C#方法的执行速度可能比调用外部C函数更快一些,因为它不会出现由于离开托管堆的执行环境而造成负载。

fixed语句

fixed语句是用来锁定托管对象的,如前面例子中的位图。在程序的执行过程中,许多对象都是从堆中分配和回收的。为了避免内存浪费或碎片,垃圾回收器会移动这些对象。因此,如果一个对象的地址在引用时发生变化,那么指向该对象的指针就变成无效的了,所以fixed语句会告诉垃圾回收器“锁定”这个对象,而且不要移动它。由于这可能对运行时效率产生一定的影响,所以fixed代码块只能短暂使用,而且堆分配应避免出现在fixed代码块中。

在一个fixed语句中,可以获得一个指向任意数值类型、数值类型数组或字符串的指针。对于数组和字符串,这个指针实际上是指向第一个元素,它是一种数值类型。

在引用类型中以内联方式声明的数值类型是要求锁定该引用类型的,如下所示:

class Test
{
int x;
static void Main()
{
Test test = new Test();
unsafe
{
fixed(int* p = &test.x)
{
*p = 9;
}
System.Console.WriteLine(test.x);
}
}
}


指向成员的指针运算符

除了&和*运算符,C#还支持C++中的->运算符,可以在结构体中使用:

struct Test
{
int x;
unsafe static void Main()
{
Test test = new Test();
Test* p = &test;
p->x = 9;
System.Console.WriteLine(test.x);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C# 不安全代码 指针