instrução fixed – fixar uma variável para operações de ponteiro
A instrução fixed
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 é alterado 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.
Observação
Você pode usar a instrução fixed
somente em um contexto não seguro. O código que contém blocos não seguros deve ser compilado com a opção do 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 de matriz.
Com um endereço de uma variável. Use o operador address-of
&
, como mostra o seguinte exemplo: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 instrução
fixed
garante que o coletor de lixo não realoque ou descarte a instância de objeto que o 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 uma variávelref
para um tipo não gerenciado. Os tipos do .NET System.Span<T> e System.ReadOnlySpan<T> fazem uso desse padrão. Você pode fixar instâncias span, 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, veja a referência de API Span<T>.GetPinnableReference().
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.
É possível 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 expressão stackalloc
.
Você também pode usar a palavra-chave fixed
para declarar um buffer de tamanho fixo.
Especificação da linguagem C#
Para obter mais informações, confira as seguintes seções da especificação da linguagem C#: