C# 之不安全代码(1)

引子

C#是.Net平台上主流的开发语言,和经典的C/C++不同的是,C#所编写的代码是托管代码,由GC来管理内存,省去了new/delete的烦恼。但是,由于某些特殊的要求,比如和底层的操作系统接口,访问内存映射设备或者实现对时间要求苛刻的算法时,C#提供了不安全代码。

不安全上下文

不安全代码只能写在不安全上下文中。

通过unsafe 修饰符可以修饰:

class, struct, interface, or delegate

field, method, property, event, indexer, operator, instance constructor, destructor, or static constructor

unsafe-statement-block

指针的类型

在不安全上下文中,指针类型和引用类型或是值类型一样。但是,指针类型可以用在不安全上下文之外的typeof中,虽然这么做不安全。

Type t = typeof(Int32*);返回的是System.Int32*

指针类型是用非托管类型或是void加上*来表示的。

pointer-type:
unmanaged-type  *
void  *

unmanaged-type:
type

在*前面的指针类型被称为指针类型的引用类型。它表明了指针变量的值指向的变量的类型。

非托管类型不是引用类型,也不包含任何嵌套的引用类型的成员。

非托管类型就是下面的一种:

·        sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool.

·        Any enum-type.

·        Any pointer-type.

·        Any user-defined struct-type that contains fields of unmanaged-types only.

例子:

Example
Description
byte*
Pointer to byte
char*
Pointer to char
int**
Pointer to pointer to int
int*[]
Single-dimensional array of pointers to int
void*
Pointer to unknown type



和C/C++不同的是,声明多个指针变量需要:

int *p1,*p2;

但是在C#中,int* p1,p2就声明了两个指针变量,并且*是在类型之后,不是在变量名之前。

和引用类型相同的是,指针可以为null(所有位为0),如果访问一个指向null的指针会引发不可预知的结果。

Void* 表示一个指针指向未知类型。因为指向未知类型,所以不能通过*来访为指向的变量,也不能对指针进行数学运算。但是,void*可以转换为任何指针类型,反之亦然。

指针类型是一个单独的类型。指针类型不是继承自System.Object,,并且两者也不能互相转换。同样装箱和拆箱也不适合指针类型。但是不同类型指针之间可以互相转换。

指针类型不能用于类型参数,当泛型方法的类型参数为指针类型会调用失败。

指针类型还可用于易变字段类型。

虽然指针还能通过ref和out来传递,但是会造成不可预知的行为,当指针指向一个已经不存在的本地变量,或是指向一个实际不再固定的固定对象。比如:
  1. using System;

  2. class Test
  3. {
  4.       static int value = 20;

  5.       unsafe static void F(out int* pi1, ref int* pi2) {
  6.             int i = 10;
  7.             pi1 = &i;

  8.             fixed (int* pj = &value) {
  9.                   // ...
  10.                   pi2 = pj;
  11.             }
  12.       }

  13.       static void Main() {
  14.             int i = 10;
  15.             unsafe {
  16.                   int* px1;
  17.                   int* px2 = &i;

  18.                   F(out px1, ref px2);

  19.                   Console.WriteLine("*px1 = {0}, *px2 = {1}",
  20.                         *px1, *px2);      // undefined behavior
  21.             }
  22.       }
  23. }
复制代码
方法可以返回指针类型。
  1. unsafe static int* Find(int* pi, int size, int value) {
  2.       for (int i = 0; i < size; ++i) {
  3.             if (*pi == value) 
  4.                   return pi;
  5.             ++pi;
  6.       }
  7.       return null;
  8. }
复制代码
主要有几个操作符:

·        *被用作间接访问

·        ->被用作通过指针来访为结构的成员

·          []用来做指针的索引器

·        &用来获得变量的地址

·        ++和—用来自增和自减指针

·        +和-用来做指针的算术运算

·        ==, !=, <, >, <=, and =>用来比较指针

·  stackalloc可以从栈上分配内存

·  fixed用来临时固定一个变量,所以它的地址总是可以得到的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值