Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Os operadores de ponteiro permitem que você pegue o endereço de uma variável (&), desreferencie um ponteiro (*), compare valores de ponteiro e adicione ou subtraia ponteiros e inteiros.
A linguagem C# faz referência a documentos da versão mais recentemente lançada da linguagem C#. Ele também contém a documentação inicial para funcionalidades em pré-visualizações públicas para o próximo lançamento do idioma.
A documentação identifica qualquer recurso introduzido pela primeira vez nas três últimas versões do idioma ou nas versões prévias públicas atuais.
Dica
Para descobrir quando um recurso foi introduzido pela primeira vez em C#, consulte o artigo sobre o histórico de versão da linguagem C#.
Use os seguintes operadores para trabalhar com ponteiros:
- Operador unário
&(address-of): para obter o endereço de uma variável - Operador Unary
*(indireção de ponteiro ): para obter a variável apontada por um ponteiro - Os operadores
->(acesso de membro) e[](acesso de elemento) - Operadores aritméticos
+,-,++e-- - Operadores de comparação
==,!=,<,>,<=e>=
Para obter informações sobre tipos de ponteiros, veja Tipos de ponteiro.
Observação
Qualquer operação com ponteiros exige um contexto unsafe. Você deve compilar o código que contém blocos não seguros com a opção do compilador AllowUnsafeBlocks .
Operador address-of &
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. Variáveis que residem em locais de armazenamento que o coletor de lixo pode afetar (por exemplo, realocar) são chamadas de variáveis móveis . Campos de objeto e elementos de matriz são exemplos de variáveis móveis. Você pode obter o endereço de uma variável móvel se você "corrigir" ou "fixar", usando uma fixed instrução. O endereço obtido é válido somente dentro do bloco de uma instrução fixed. O exemplo a seguir mostra como usar uma instrução fixed 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 nem de um valor.
Para obter mais informações sobre variáveis fixas e móveis, veja a seção Variáveis fixas e móveis da Especificação de linguagem C#.
O operador binário & computa o AND lógico de seus operandos Boolianos ou o AND lógico bit a bit de seus operandos integrais.
Operador de indireção de ponteiro*
O operador * de indireção de ponteiro unário acessa a variável à qual seu operando aponta. Também é conhecido como o operador de desreferenciar. O operando do operador * deve ser de um tipo de 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 * computa o produto de seus operandos numéricos.
Operador de acesso de membro do ponteiro ->
O operador -> combina indireção do ponteiro e acesso de membro. Se x for um ponteiro do tipo T* e y for um membro acessível do tipo T, uma expressão do formulário
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)
}
}
Você não pode usar o -> operador em uma expressão do tipo void*.
Operador de acesso de elemento de ponteiro []
Para uma expressão p de um tipo de ponteiro, um acesso de elemento de ponteiro do formulário p[n] é avaliado como *(p + n). O valor n deve ser de um tipo implicitamente conversível para int, uintou longulong. Para obter informações sobre o comportamento do operador + com ponteiros, veja a seção Adição ou subtração de um valor integral para ou de um ponteiro.
O exemplo a seguir demonstra como acessar elementos de matriz 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 expressão stackalloc aloca um bloco de memória na pilha.
Observação
O operador de acesso de elemento de ponteiro não verifica se há erros fora dos limites.
Não é possível usar [] para acesso de elemento de ponteiro com uma expressão do tipo void*.
Você também pode usar o operador [] para acesso de indexador ou elemento de matriz.
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 decrementar um ponteiro
Você não pode executar essas operações com ponteiros do tipo void*.
Para obter informações sobre operações aritméticas com suporte usando tipos numéricos, consulte 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 um tipo implicitamente conversível para int, uintou long, ulongadição e subtração funcionam da seguinte maneira:
- Ambos
p + nen + pdê-lhe um ponteiro do tipoT*. Você obtém esse ponteiro adicionandon * sizeof(T)ao endereço ao qualpaponta. - A
p - nexpressão fornece um ponteiro do tipoT*. Você obtém esse ponteiro subtraindon * sizeof(T)do endereço para o qualpaponta.
O sizeof operador obtém o tamanho de um tipo em bytes.
O exemplo a seguir 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 de ponteiro
Para dois ponteiros p1 e p2 de tipo T*, a expressão p1 - p2 fornece a diferença entre os endereços que p1 e p2 apontam para, divididos por sizeof(T). O resultado é do tipo long. Em outras palavras, p1 - p2 é calculado como ((long)(p1) - (long)(p2)) / sizeof(T).
O exemplo a seguir mostra a subtração de ponteiro:
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
}
Incrementar e decrementar ponteiros
O operador de incremento ++adiciona 1 ao operando do ponteiro. O operador de decremento --subtrai 1 do operando do ponteiro.
Ambos os operadores dão suporte a dois formulários: postfix (p++ e p--) e prefixo (++p e --p). O resultado de p++ e p-- é o valor de pantes da operação. O resultado de ++p e --p é o valor de pdepois da operação.
O exemplo a seguir demonstra o comportamento dos operadores de incremento de sufixo 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 ponteiro
Você pode usar os operadores ==, !=, <, >, <= e >= para comparar os operandos de qualquer tipo de ponteiro, incluindo void*. Esses operadores comparam os endereços fornecidos pelos dois operandos como se fossem inteiros sem sinal.
Para obter informações sobre o comportamento desses operadores para operandos de outros tipos, veja os artigos Operadores de igualdade e Operadores de comparação.
Precedência do operador
A lista a seguir ordena operadores relacionados a ponteiro começando da precedência mais alta até a mais baixa:
- Operadores de incremento
x++e decrementox--sufixados e os operadores->e[] - Operadores de incremento
++xe decremento--xprefixados e os operadores&e* - Operadores de adição
+e- - Operadores de comparação
<,>,<=e>= - Operadores de igualdade
==e!=
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 de operador do artigo Operadores C# .
Capacidade de sobrecarga do operador
Você não pode sobrecarregar os operadores &*->relacionados ao ponteiro e [] em um tipo definido pelo usuário.
Especificação da linguagem C#
Para obter mais informações, confira as seguintes seções da especificação da linguagem C#:
- Variáveis fixas e móveis
- O operador address-of
- Indireção de ponteiro
- Acesso de membro do ponteiro
- Acesso de elemento do ponteiro
- Aritmética do ponteiro
- Incrementar e decrementar ponteiros
- Comparação de ponteiros