Como trabalhar com ponteiros em .NET ?
Poucos sabem que
é possível trabalhar diretamente com ponteiros em .NET. Outros até sabem, mas
evitam mexer. Em geral não é recomendado que se trabalhe em modo inseguro em
.NET, que é requisito para trabalhar com ponteiros.
Os ponteiros são
especiais e não herdam de Object, sendo assim uma exceção no ambiente comum da
CLR. Para trabalhar com ponteiros é necessário utilizar a palavra reservada unsafe para esta ação.
Habilitando o modo inseguro no projeto |
Para
utilizar de forma insegura é necessário que seja habilitada a opção de uso de
código inseguro na aplicação. Clique com o botão direito no projeto que tornar
inseguro (Solution Explorer). Vá até a opção Build nas abas laterais a
esquerda. Em General, habilite o checkbox com a frase ‘Allow unsafe code’.
Consulte a figura a seguir para auxiliar.
Veja uma exemplo
de código que utiliza o contexto inseguro:
public static
void Main()
{
unsafe
{
int* i;
int
j = 10;
i = &j;
Console.Write(i->ToString());
}
}
Para trabalhar
com ponteiros é necessário o uso de
operadores específicos. Repare o código acima que utiliza : int*,
i=&j, i->ToString(). Estas notações são comuns na linguagem C++,
mas são pouco utilizadas em .Net. Estas notações são válidas apenas em
contextos inseguros. Veja a seguir uma lista com os operadores utilizados em
ponteiros em .NET:
Operador
|
Função
|
*
|
Faz acesso a um ponteiro
|
-> | Utiliza o conteúdo de um ponteiro |
[] | Acessa o ponteiro como um vetor. Cuidado! Pode-se fazer acesso a posições de memória que não estão relacionados ao contexto desejado. |
& | Obtem dados do destino do apontamento de um vetor |
++, -- | Incrementa ou decrementa um ponteiro |
+, - | Realiza uma operação aritmética |
==, !=, <, >, <=, >= | Compara ponteiros |
Stackalloc | Aloca memória na stack |
fixed statement | Define endereço de ponteiro que aponta para destino que não corresponde ao desejado |
Os ponteiros dão
flexibilidade para o desenvolvedor. Porém esta flexibilidade pode ser muito
prejudicial por não ser tratada diretamente pela CLR. Os ponteiros em .Net
podem apontar apenas para seus tipos primitivos: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, ou bool;
enumerações; qualquer outro tipo de ponteiro; structs que não tenham campos não
gerenciados (campos por referência).
Existe um tipo
especial para ponteiros que é o void*. A microsoft não recomenda o uso deste
tipo. O tipo void* é utilizado para guardar apontamentos sem identificação do
tipo de valor destino ou capacidade de tratamento.
Também é
possível trabalhar com um ponteiro como se fosse um vetor. Diferentemente dos
vetores de alto nível, é possível acessar posições de memória que não
correspondam ao vetor em questão, por não ser tratado. No exemplo a seguir, as
posições 0 e 1 são impressas na tela, porém, só a posição 0 é conhecida pela aplicação.
public static
void Main()
{
unsafe
{
int* i;
int
j = 10;
i = &j;
Console.Write(i[0] + “\n” + i[1]);
}
}
Como funcionam internamente os Arrays em .NET?
Os arrays são
estruturas de dados fundamentais para a maioria da linguagens de programação.
Um agrupamento de dados de um mesmo tipo é dimensionado na memória. Os arrays
internamente são ponteiros que acessam posições de memória pré-definidos para
leitura e escrita de um tipo específico de dado. Veja a seguir as 2 formas de
criação de arrays em C#:
public static
void Main()
{
int[] meu_array = new int[50];
meu_array[10] = 30;
System.Array
meu_array2 = new int[50];
meu_array2.SetValue(30, 10);
Console.WriteLine(meu_array[10].ToString());
Console.WriteLine(meu_array2.GetValue(10).ToString());
}
A notação type[] vale para qualquer tipo de
dado, seja por valor ou por referência. Esta notação converte internamente o
tipo para um tipo System.Array, e desta forma este encapsulamento é guardado na
heap.
Repare que a segunda notação não oferece
algo como:
this[int index] { get; set; }.
Sendo assim, é mais fácil trabalhar com a
notação type[].
Nenhum comentário:
Postar um comentário