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

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

相关推荐

  • 3.15C#语言的可访问性(Accessibility)

    访问修饰符 程序集 是通过在单个编译中编译一个或多个 .cs 文件而创建的 .dll 或 .exe。 调用方的位置 public protected internal protected internal private protected private 在类内 ✔️️ ✔️ ✔️ ✔️ ✔️ ✔️ 派生类(相同程序…

    C#语言教程 2021年3月15日
    06320
  • 3.5C#引用类型之接口(Interface)

    1.接口声明 接口包含一组非抽象class或struct必须实现的相关功能的定义。 2.继承 接口 可以继承自多个基接口。 3.实现 3.1实现 类 或 结构 可以实现多个接口,实现接口的类或结构必须实现其所有未提供默认实现的成员并匹配接口中的成员签名,非必须重写实现具有默认实现的成员。 3.2默认实现 接口…

    C#语言教程 2021年3月5日
    06350
  • 2.3C#数据成员之字段(Field)

    字段是与类或类实例相关联的变量,字段定义存储位置。 1.字段声明和初始化 同变量。 2.字段分类 名称 修饰符 静态字段 用 static 修饰 实例字段 无 static 修饰 3.readonly修饰符 在字段声明中,readonly 修饰符表示只能 在声明期间初始化时或在同一个类的静态或实例构造函数中 …

    C#语言教程 2021年2月3日
    06570

发表回复

登录后才能评论