instrução fixa - fixar uma variável para operações de ponteiro
A fixed
instrução impede que o coletor de lixo realoque uma variável móvel e declara um ponteiro para essa variável. O endereço de uma variável fixa ou fixada não muda durante a execução da instrução. Você pode usar o ponteiro declarado somente dentro da instrução correspondente fixed
. O ponteiro declarado é somente leitura e não pode ser modificado:
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.
Nota
Você pode usar a fixed
instrução somente em um contexto inseguro . O código que contém blocos não seguros deve ser compilado com a opção de compilador AllowUnsafeBlocks.
Você pode inicializar o ponteiro declarado da seguinte maneira:
Com uma matriz, como mostra o exemplo no início deste artigo. O ponteiro inicializado contém o endereço do primeiro elemento da matriz.
Com um endereço de uma variável. Use o operador address-of, como mostra o exemplo a
&
seguir:unsafe { int[] numbers = [10, 20, 30]; fixed (int* toFirst = &numbers[0], toLast = &numbers[^1]) { Console.WriteLine(toLast - toFirst); // output: 2 } }
Os campos de objeto são outro exemplo de variáveis móveis que podem ser fixadas.
Quando o ponteiro inicializado contém o endereço de um campo de objeto ou um elemento de matriz, a
fixed
instrução garante que o coletor de lixo não realoque ou descarte a ocorrência do objeto que contém durante a execução do corpo da instrução.Com a instância do tipo que implementa um método chamado
GetPinnableReference
. Esse método deve retornar umaref
variável de um tipo não gerenciado. O .NET tipos System.Span<T> e System.ReadOnlySpan<T> fazer uso desse padrão. Você pode fixar instâncias de extensão, como mostra o exemplo a seguir: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 } }
Para obter mais informações, consulte a referência da Span<T>.GetPinnableReference() API.
Com uma cadeia de caracteres, como mostra o exemplo a seguir:
unsafe { var message = "Hello!"; fixed (char* p = message) { Console.WriteLine(*p); // output: H } }
Com um buffer de tamanho fixo.
Você pode alocar memória na pilha, onde ela não está sujeita à coleta de lixo e, portanto, não precisa ser fixada. Para fazer isso, use uma stackalloc
expressão.
Você também pode usar a fixed
palavra-chave para declarar um buffer de tamanho fixo.
Especificação da linguagem C#
Para obter mais informações, consulte as seguintes seções da especificação da linguagem C#: