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# 言語仕様」の次のセクションを参照してください。
関連項目
.NET