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 uma ref 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#:

Consulte também