3.14C#类型之指针(Pointer)类型

1.指针类型声明

类型为referent类型*的指针变量存储的是类型为referent类型的固定变量或可移动变量的地址。只有非托管类型可为referent类型

任何指针类型可以分配 null

//声明未初始化
//比如:byte*、int*、double*、char*.
referent类型* 指针变量;

//p 是指向整数的指针。
int* p;

//p 是指向整数的指针的指针。
int** p;

//p 是指向整数的指针的一维数组。
int*[] p;

//p 是指向字符的指针。
char* p;

//p 是指向未知类型的指针。
//允许但不推荐
void* p;

2.继承

指针类型没有从 System.Object 继承。

3.类型转换

指针类型与 System.Object 之间不存在转换。

任何指针类型都可以隐式转换为 void* 类型。任何指针类型可以使用强制转换表达式显式转换为任何其它指针类型。

任何整数类型可以显式转换为指针类型,或将任何指针类型显式转换为整数类型。

4.装箱(Boxing)和取消装箱(Unboxing)

指针类型不支持装箱与取消装箱。

5.函数指针(Function pointer)

可以使用 delegate* 语法定义函数指针。需在 unsafe 上下文中使用。

可以调用采用 delegate*(或返回 delegate*)的方法。

//第一种方法使用 System.Func<T1,T2,TResult> 委托类型。
public static T Combine<T>(Func<T, T, T> combinator, T left, T right) => 
    combinator(left, right);


// 第二种方法使用具有相同参数和返回类型的 delegate* 声明。
public static T UnsafeCombine<T>(delegate*<T, T, T> combinator, T left, T right) => 
    combinator(left, right);

只可在 static 函数上使用 & 运算符获取函数的地址。(此规则适用于成员函数和本地函数)。

static int localMultiply(int x, int y) => x * y;
int product = UnsafeCombine(&localMultiply, 3, 4);

6.unsafe关键字

unsafe 关键字表示不安全上下文,任何带指针的运算都需要使用 unsafe 上下文。

若要编译不安全代码,必须指定 AllowUnsafeBlocks 编译器选项。不能通过公共语言运行时验证不安全代码。

如果在类型或成员的声明中使用 unsafe 修饰符,则类型或成员的整个正文范围均被视为不安全上下文。不安全上下文的范围从参数列表到方法的结尾。

//参数包含指针
unsafe static void FastCopy ( byte* ps, byte* pd, int count ) {...}
unsafe static void FastCopy(byte[] src, byte[] dst, int count)
{
    //方法体包含指针
}

还可以使用不安全块从而能够使用该块内的不安全代码。

unsafe
{
    //代码块包含指针
}

7.&(获取固定变量的地址)

& (address-of运算符)用于获取固定变量(驻留在不受垃圾回收器操作影响的存储位置的变量)的地址。

类型A 变量a = 值;
类型A* 指针变量b = &变量a;

8.fixed语句(获取可移动变量的地址)

fixed 语句用于固定可移动变量(驻留在受垃圾回收器影响的存储位置的变量)并获取可移动变量的地址,获取的地址仅在 fixed 语句块中有效。

fixed 语句将为托管(managed)变量设置一个指针(指针为未托管类型),并在该语句的执行过程中“单边锁定”该变量。

fixed语句可以固定 数组、字符串、固定大小的缓冲区(fixed-size buffer)或变量的地址(对象字段、数组元素)或非托管(unmanaged)变量,还可以固定任何实现了GetPinnableReference方法的类型。GetPinnableReference 方法必须返回一个未托管(unmanaged)类型的 ref 变量。比如:System.Span<T> 结构和 System.ReadOnlySpan<T>结构。

fixed 语句仅允许存在于不安全上下文中。 

在 fixed 语句中初始化的指针为只读变量。 如果想要修改指针值,必须声明第二个指针变量,并修改它。

fixed (byte* ps = srcarray, pd = dstarray)
{
    byte* pSourceCopy = ps;

    // point to the next element.
    pSourceCopy++; 
    // invalid: cannot modify ps, as it is declared in the fixed statement.
    ps++; 
}

8.1用于数组

//数组
fixed (double* p = arr) { /*...*/ }
//等同于以下代码
//变量地址(数组元素)
double[] arr = { 0, 1.5, 2.3, 3.4, 4.0, 5.9 };
fixed (double* p = &arr[0]) { /*...*/ }

8.2用于字符串

//字符串
string str = "Hello World";
fixed (char* p = str) { /*...*/ }
//以下语句无效,因为str[0]是char,它是值,不是变量。
fixed (char* p = &str[0]) { /*...*/ }

8.3用于固定大小的缓冲区(Fixed-size buffer)

使用 fixed 语句来创建在数据结构中具有固定大小的数组的缓冲区。当编写与其它语言或平台的数据源进行互操作的方法时,固定大小的缓冲区很有用。 固定的数组可以采用允许用于常规结构成员的任何特性或修饰符。 唯一的限制是数组类型必须为 boolbytecharshortintlongsbyteushortuintulongfloat 或 double

private fixed char name[30];

8.4用于变量地址

//变量地址(对象字段)
class Point
{
    public int x;
    public int y;
}

unsafe private static void ModifyFixedStorage()
{
    Point pt = new Point();

    fixed (int* p = &pt.x)
    {
        *p = 1;
    }
}

9.*(获取指针指向的变量)

*(指针间接运算符,又称”取消引用运算符“)用于获取指针指向的变量,操作数必须是指针类型。

类型A 变量a = 值;
类型A* 指针变量b = &变量a;
*指针变量b = 新值;

原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/csharp/csharplang/14048.html

(0)
上一篇 2021年3月13日 15:58
下一篇 2021年3月15日 01:53

相关推荐

  • 1.1C#语言的三种注释(Comment)

    1.单行注释 2.多行注释 3.文档注释

    C#语言教程 2021年1月1日
    01830
  • 5.3C#异步编程完整示例

    以下将用”如何烹饪早餐”示例来解释异步: 倒一杯咖啡。 加热平底锅,然后煎两个鸡蛋。 煎三片培根。 烤两片面包。 在烤面包上加黄油和果酱。 倒一杯橙汁。 1.同步代码 同步准备的早餐大约花费了 30 分钟,因为总耗时是每个任务耗时的总和。 这样做早餐花费的时间要长得多,有些食物在上桌之前就已经凉…

    C#语言教程 2021年5月3日
    02590
  • 3.9C#引用类型之特性(Attribute)

    1.特性声明 所有特性类都直接或间接派生自 System.Attribute 基类。 以下示例声明了 HelpAttribute 特性。 2.调用特性 调用特性时,通过用方括号 ([]) 将特性名称以及实参括起来,并置于应用该特性的实体的声明上方。可以将多个特性附加到实体的声明上。对于给定实体,一些…

    C#语言教程 2021年3月9日
    0740

发表评论

登录后才能评论