分享方式:


fixed 陳述式 - 固定指標作業的變數

fixed 陳述式可防止記憶體回收行程重新放置可移動變數,並宣告該變數的指標。 固定或釘選變數的位址不會在陳述式執行期間變更。 您只能在對應的 fixed 陳述式內部使用已宣告的指標。 已宣告的指標為唯讀,無法進行修改:

unsafe
{
    byte[] bytes = [1, 2, 3];
    fixed (byte* pointerToFirst = bytes)
    {
        Console.WriteLine($"The address of the first array element: {(long)pointerToFirst:X}.");
        Console.WriteLine($"The value of the first array element: {*pointerToFirst}.");
    }
}
// Output is similar to:
// The address of the first array element: 2173F80B5C8.
// The value of the first array element: 1.

注意

您只能將 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]);  
            }
            // output: 203040
        }
    }
    

    如需詳細資訊,請參閱 Span<T>.GetPinnableReference() API 參考。

  • 使用字串,如下列範例所示:

    unsafe
    {
        var message = "Hello!";
        fixed (char* p = message)
        {
            Console.WriteLine(*p);  // output: H
        }
    }
    
  • 使用固定大小緩衝區

您可以配置堆疊上的記憶體,此處不受記憶體回收限制,因此不需要予以釘選。 若要這樣做,請使用 stackalloc 運算式

您也可以使用 fixed 關鍵字來宣告固定大小緩衝區

C# 語言規格

如需詳細資訊,請參閱 C# 語言規格的下列幾節:

另請參閱