Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Os operadores de ponteiro permitem que você pegue o endereço de uma variável (&), cancele a referência de um ponteiro (*), compare valores de ponteiro e adicione ou subtraia ponteiros e inteiros.
A referência da linguagem C# documenta a versão mais recentemente lançada da linguagem C#. Contém também documentação inicial para funcionalidades em versões preliminares públicas para a próxima versão da linguagem.
A documentação identifica qualquer funcionalidade introduzida pela primeira vez nas últimas três versões da língua ou em pré-visualizações públicas atuais.
Sugestão
Para saber quando uma funcionalidade foi introduzida pela primeira vez em C#, consulte o artigo sobre o histórico de versões da linguagem C#.
Use os seguintes operadores para trabalhar com ponteiros:
- Operador unário
&(endereço de): para obter o endereço de uma variável - Operador unário
*(indireção do apontador): para obter a variável apontada por um ponteiro - Os
->operadores (acesso de membros) e[](acesso de elementos) - Operadores
+aritméticos ,-,++, e-- - Operadores
==de comparação , ,!=<,>,<=, e>=
Para obter informações sobre tipos de ponteiro, consulte Tipos de ponteiro.
Nota
Qualquer operação com ponteiros requer um contexto inseguro . Deve compilar o código que contém blocos inseguros com a opção do compilador AllowUnsafeBlocks .
Endereço do operador &
O operador unário & retorna o endereço de seu operando:
unsafe
{
int number = 27;
int* pointerToNumber = &number;
Console.WriteLine($"Value of the variable: {number}");
Console.WriteLine($"Address of the variable: {(long)pointerToNumber:X}");
}
// Output is similar to:
// Value of the variable: 27
// Address of the variable: 6C1457DBD4
O operando do & operador deve ser uma variável fixa.
Variáveis fixas são variáveis que residem em locais de armazenamento que o coletor de lixo não afeta. No exemplo anterior, a variável number local é uma variável fixa porque reside na pilha. As variáveis que residem em locais de armazenamento que o coletor de lixo pode afetar (por exemplo, realocar) são chamadas variáveis móveis . Campos de objeto e elementos de matriz são exemplos de variáveis móveis. Pode obter o endereço de uma variável móvel se a "fixar" ou "fixar" usando uma fixed instrução. O endereço obtido é válido apenas dentro do bloco de uma fixed declaração. O exemplo a seguir mostra como usar uma fixed instrução e o & operador:
unsafe
{
byte[] bytes = { 1, 2, 3 };
fixed (byte* pointerToFirst = &bytes[0])
{
// The address stored in pointerToFirst
// is valid only inside this fixed statement block.
}
}
Não é possível obter o endereço de uma constante ou de um valor.
Para obter mais informações sobre variáveis fixas e móveis, consulte a seção Variáveis fixas e móveis da especificação da linguagem C#.
O operador binário & calcula o AND lógico de seus operandos booleanos ou o bit lógico AND de seus operandos integrais.
Operador de indireção de ponteiro *
O operador * de indireção do ponteiro unário acede à variável para a qual o seu operando aponta. Também é conhecido como operador de desreferência. O operando do * operador deve ser do tipo ponteiro.
unsafe
{
char letter = 'A';
char* pointerToLetter = &letter;
Console.WriteLine($"Value of the `letter` variable: {letter}");
Console.WriteLine($"Address of the `letter` variable: {(long)pointerToLetter:X}");
*pointerToLetter = 'Z';
Console.WriteLine($"Value of the `letter` variable after update: {letter}");
}
// Output is similar to:
// Value of the `letter` variable: A
// Address of the `letter` variable: DCB977DDF4
// Value of the `letter` variable after update: Z
Não é possível aplicar o * operador a uma expressão do tipo void*.
O operador binário * calcula o produto de seus operandos numéricos.
Operador de acesso membro do ponteiro ->
O -> operador combina indireção de ponteiro e acesso de membro. Se x é um ponteiro do tipo T* e y é um membro acessível do tipo T, uma expressão da forma
x->y
é equivalente a
(*x).y
O exemplo a seguir demonstra o uso do -> operador:
public struct Coords
{
public int X;
public int Y;
public override string ToString() => $"({X}, {Y})";
}
public class PointerMemberAccessExample
{
public static unsafe void Main()
{
Coords coords;
Coords* p = &coords;
p->X = 3;
p->Y = 4;
Console.WriteLine(p->ToString()); // output: (3, 4)
}
}
Não podes usar o -> operador numa expressão do tipo void*.
Operador de acesso ao elemento do ponteiro []
Para uma expressão p de tipo ponteiro, um acesso a elementos de ponteiro da forma p[n] é avaliado como *(p + n). O valor n deve ser de um tipo implicitamente convertível em int, uint, long, ou ulong. Para obter informações sobre o + comportamento do operador com ponteiros, consulte a seção Adição ou subtração de um valor integral de ou para um ponteiro .
O exemplo seguinte demonstra como aceder a elementos do array usando um ponteiro e o [] operador:
unsafe
{
char* pointerToChars = stackalloc char[123];
for (int i = 65; i < 123; i++)
{
pointerToChars[i] = (char)i;
}
Console.Write("Uppercase letters: ");
for (int i = 65; i < 91; i++)
{
Console.Write(pointerToChars[i]);
}
}
// Output:
// Uppercase letters: ABCDEFGHIJKLMNOPQRSTUVWXYZ
No exemplo anterior, uma stackalloc expressão aloca um bloco de memória na pilha.
Nota
O operador de acesso ao elemento de ponteiro não verifica se há erros fora dos limites.
Não é possível usar [] para acesso ao elemento de ponteiro com uma expressão do tipo void*.
Você também pode usar o operador para [] a elementos de matriz ou indexadores.
Operadores aritméticos de ponteiro
Você pode executar as seguintes operações aritméticas com ponteiros:
- Adicionar ou subtrair um valor integral de ou para um ponteiro
- Subtrair dois ponteiros
- Incrementar ou diminuir um ponteiro
Não é possível executar essas operações com ponteiros do tipo void*.
Para informações sobre operações aritméticas suportadas usando tipos numéricos, veja Operadores aritméticos.
Adicionar ou subtrair um valor integral de ou para um ponteiro
Para um ponteiro p de tipo T* e uma expressão n de tipo implicitamente convertível em int, uint, long, ou ulong, adição e subtração funcionam da seguinte forma:
- Ambos
p + nen + pdão-te um indicador do tipoT*. Obtém-se esta dica ao adicionarn * sizeof(T)ao endereço para ondepaponta. - A
p - nexpressão dá-lhe um ponteiro do tipoT*. Obtém-se este indicador subtraindon * sizeof(T)do endereço para ondepaponta.
O sizeof operador obtém o tamanho de um tipo em bytes.
O exemplo seguinte mostra como usar o + operador com um ponteiro:
unsafe
{
const int Count = 3;
int[] numbers = new int[Count] { 10, 20, 30 };
fixed (int* pointerToFirst = &numbers[0])
{
int* pointerToLast = pointerToFirst + (Count - 1);
Console.WriteLine($"Value {*pointerToFirst} at address {(long)pointerToFirst}");
Console.WriteLine($"Value {*pointerToLast} at address {(long)pointerToLast}");
}
}
// Output is similar to:
// Value 10 at address 1818345918136
// Value 30 at address 1818345918144
Subtração do ponteiro
Para dois ponteiros p1 e p2 do tipo T*, a expressão p1 - p2 dá-lhe a diferença entre os endereços que p1 e p2 apontam para, dividida por sizeof(T). O resultado é do tipo long. Por outras palavras, p1 - p2 é calculado como ((long)(p1) - (long)(p2)) / sizeof(T).
O exemplo seguinte mostra a subtração de ponteiros:
unsafe
{
int* numbers = stackalloc int[] { 0, 1, 2, 3, 4, 5 };
int* p1 = &numbers[1];
int* p2 = &numbers[5];
Console.WriteLine(p2 - p1); // output: 4
}
Incremento e decréscimo do ponteiro
O ++ operador de incremento adiciona 1 ao seu operando de ponteiro. O -- operador de decréscimo subtrai 1 de seu operando de ponteiro.
Ambos os operadores suportam duas formas: postfixo (p++ e p--) e prefixo (++p e --p). O resultado de p++ e p-- é o valor de antes da poperação. O resultado de ++p e --p é o valor de papós a operação.
O exemplo a seguir demonstra o comportamento dos operadores de incremento postfix e prefixo:
unsafe
{
int* numbers = stackalloc int[] { 0, 1, 2 };
int* p1 = &numbers[0];
int* p2 = p1;
Console.WriteLine($"Before operation: p1 - {(long)p1}, p2 - {(long)p2}");
Console.WriteLine($"Postfix increment of p1: {(long)(p1++)}");
Console.WriteLine($"Prefix increment of p2: {(long)(++p2)}");
Console.WriteLine($"After operation: p1 - {(long)p1}, p2 - {(long)p2}");
}
// Output is similar to
// Before operation: p1 - 816489946512, p2 - 816489946512
// Postfix increment of p1: 816489946512
// Prefix increment of p2: 816489946516
// After operation: p1 - 816489946516, p2 - 816489946516
Operadores de comparação de ponteiros
Você pode usar os ==operadores , !=, <, ><=, e >= para comparar operandos de qualquer tipo de ponteiro, incluindo void*. Estes operadores comparam os endereços dados pelos dois operandos como se fossem inteiros sem sinal.
Para obter informações sobre o comportamento desses operadores para operandos de outros tipos, consulte os artigos Operadores de igualdade e Operadores de comparação.
Precedência dos operadores
A lista a seguir ordena os operadores relacionados ao ponteiro a partir da maior precedência para a mais baixa:
- Operadores de incremento e decréscimo
x++x--pós-fixo e os->operadores e[] - Operadores de incremento
++xe decréscimo--xde prefixo e os&operadores e* -
+Aditivos e-operadores - Comparação
<,>,<=, e>=operadores - Igualdade
==e!=operadores
Use parênteses, (), para alterar a ordem de avaliação imposta pela precedência do operador.
Para obter a lista completa de operadores C# ordenados por nível de precedência, consulte a seção Precedência do operador do artigo Operadores C#.
Capacidade de sobrecarga do operador
Não podes sobrecarregar os operadores &relacionados com o ponteiro , *, ->, e [] num tipo definido pelo utilizador.
Especificação da linguagem C#
Para obter mais informações, consulte as seguintes seções da especificação da linguagem C#:
- Variáveis fixas e móveis
- O endereço do operador
- Indirection do ponteiro
- Acesso de membro do ponteiro
- Acesso ao elemento de ponteiro
- Aritmética do ponteiro
- Incremento e decréscimo do ponteiro
- Comparação de ponteiros