次の方法で共有


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
        }
    }
    

    オブジェクト フィールドは、固定できる移動可能な変数のもう 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# 言語仕様」の次のセクションを参照してください。

こちらも参照ください