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 ステートメントは、unsafe コンテキスト内でのみ使用できます。 unsafe ブロックを含むコードは、AllowUnsafeBlocks コンパイラ オプションを使ってコンパイルする必要があります。

宣言されたポインターは、次のように初期化することができます。

  • この記事の冒頭で示した例のように、配列を使います。 初期化されたポインターには、配列の最初の要素のアドレスが含まれています。

  • 変数のアドレスを使います。 次の例のように、アドレス取得 & 演算子を使います。

    unsafe
    {
        int[] numbers = [10, 20, 30];
        fixed (int* toFirst = &numbers[0], toLast = &numbers[^1])
        {
            Console.WriteLine(toLast - toFirst);  // output: 2
        }
    }
    

    オブジェクト フィールドは、固定できる移動可能変数のもう 1 つの例です。

    初期化されたポインターにオブジェクト フィールドまたは配列要素のアドレスが含まれる場合、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# 言語仕様」の次のセクションを参照してください。

関連項目