fixed 语句可防止垃圾回收器重新定位可移动变量,并声明指向该变量的指针。固定变量的地址在语句的持续时间内不会更改。只能在相应的 fixed 语句中使用声明的指针。 声明的指针是只读的,无法修改:

unsafe
{
    byte [ ] bytes = [1, 2, 3];
    fixed ( byte* ptr = bytes )
    {
        Console . WriteLine ( $"数组的第一个元素的地址:{( long ) ptr:X}。");
        Console.WriteLine ( $"数组的第一个元素:{*ptr}。");
    }
}
// 输出类似于:
// 第一个数组元素的地址:2173F80B5C8。
// 第一个数组元素的值:1。

备注:只能在 unsafe 的上下文中使用 fixed 语句。 必须使用 AllowUnsafeBlocks 编译器选项来编译包含不安全块的代码。

可以按如下所示初始化声明的指针:

  • 使用数组,如本文开头的示例所示。 初始化的指针包含第一个数组元素的地址。
  • 使用变量的地址。 使用 address-of & 运算符,如以下示例所示:

    unsafe
      {
      int[] numbers = [10, 20, 30];
      fixed ( int* toFirst = &numbers [ 0 ], toLast = &numbers [ ^1 ] )
          {
          Console . WriteLine ( toLast - toFirst );  // output: 2
          }
      }
    
    • 对象字段是可以固定的可移动变量的另一个示例。
    • 当初始化的指针包含对象字段或数组元素的地址时,fixed 语句保证垃圾回收器在语句主体执行期间不会重新定位或释放包含对象实例。
  • 使用实现名为 GetPinnableReference 的方法的类型的实例。 该方法必须返回非托管类型的 ref 变量。 .NET 类型 System . Span < T > 和 System . ReadOnlySpan < T > 使用此模式。可以固定跨度实例,如以下示例所示:

    unsafe
    {
      int[] numbers = [10, 20, 30, 40, 50];
      Span < int > interior = numbers . AsSpan ( ) [ 1..^1 ];
      fixed ( int* p = interior )
      {
          for ( int i = 0 ; i < interior . Length ; i++ )
          {
              Console . Write ( p [ i ] );  
          }
          // 输出:203040
      }
    }
  • 使用字符串,如以下示例所示:

    unsafe
    {
      var message = "Hello!";
      fixed ( char* p = message )
      {
          Console . WriteLine ( *p );  // 输出:H
      }
    }
  • 使用固定大小的缓冲区。

可以在堆栈上分配内存,在这种情况下,内存不受垃圾回收的约束,因此不需要固定。为此,请使用 stackalloc 表达式。

还可以使用 fixed 关键字声明固定大小的缓冲区。


兔子码农
4 声望1 粉丝

一个酒晕子


下一篇 »
C# 的 in