Operações Matemáticas com Ponteiros em C

Agora que ensinamos como fazer os ponteiros apontarem para variáveis, bem como ver e alterar o valor de variáveis através dos ponteiros, neste tutorial de nossa apostila de C, vamos dar mais exemplos reais de uso dos ponteiros, com operações de incremento, decremento, comparação de igualdade e negação.


Incremento,  Decremento e Comparando ponteiros em C

Uma das maiores utilidades dos ponteiros é fazer com que eles apontem para quantas variáveis desejarmos.
Por exemplo, podemos fazer com que um único ponteiro percorra todas as variáveis de um vetor.

E através do operador asterisco, além de percorrer as variáveis, também podemos fazer operações com elas.

A vantagem de usarmos ponteiros para percorrer e alterar variáveis é a eficiência, pois o C trabalha bem mais rápido se usarmos endereços de memória (ponteiros), ao invés de ficarmos declarando e alterando valores de variáveis.

Além disso, o uso de ponteiros para o estudo de Arquivos, Alocação Dinâmica de Memória e de Strings, na próxima seção, é essencial em nosso curso de C.

Assim  como outras variáveis, podemos, por exemplo, incrementar e decrementar ponteiros.
Como os ponteiros são variáveis para armazenar endereços de memória, se fizermos operações de incremento e decremento em ponteiros, é o endereço que irá mudar.

Porém, quando incrementamos ou decrementamos um ponteiro, seu endereço não percorre os endereços em uma unidade, ele percorre em sizeof(tipo_variável).

Por exemplo, sabemos que o tipo double ocupa 8 bytes em memória.
Se tivermos um ponteiro para um vetor tipo de variável, ele guarda a primeira posição do vetor.
Vamos supor que esse endereço seja: 2112
Quando incrementamos o ponteiro: ptr++;
O valor que ele aponta não será o pro endereço 2113, e sim pro endereço 2120, pois a próxima variável do vetor vai estar na posição 2120, já que cada variável ocupa 8 bytes e a primeira estava na posição 2112.

Ou seja, quando incrementamos ou decrementamos um ponteiro, que aponta para um tipo, ele vai percorrer o número de bytes do tamanho de seu tipo.
Se for char, o ponteiro muda sua posição de 1 byte para frente ou para trás no endereço.
Se for int, o ponteiro muda sua posição  em 4 bytes, para frente ou para trás no endereço.

O mesmo vale para outras operações matemáticas, como soma e subtração:
ptr + 1 -> endereço de onde ptr apontava + sizeof(tipo).
ptr + 2 -> endereço de onde ptr apontava, deslocado de duas variáveis para frente.
ptr – 3 -> endereço de onde ptr apontava, deslocado de duvas variáveis para trás


Exemplo de código: Calcular os termos de uma P.A usando Ponteiros em C

Peça ao usuário dois inteiros, onde o primeiro será o primeiro termo de uma P.A (Progressão Aritmética) e o segundo a razão. Em segundo, através de ponteiros, preencha um vetor com os 10 primeiros elementos dessa P.A.

Após declararmos um vetor de 10 elementos, fazemos com que o ponteiro aponte para esse vetor. Como o nome vetor nada mais é que do que o endereço do primeiro elemento.

Assim, inicialmente, nosso ponteiro aponta para o primeiro elemento do vetor, que será o primeiro elemento da P.A.

Para calcular os elementos da P.A, basta fazermos com que o próximo termo seja o atual mais a razão:
*(ptr+1) = *ptr + razao

Entramos no laço WHILE que irá percorrer todos os elementos do vetor, exceto o último (pois o último elemento é calculado pelo penúltimo, então não precisa ir até o último).

Ou seja, só irá parar depois de termos atingidos o penúltimo elemento do vetor, que é pa[8].
Como vamos usar somente ponteiros para percorrer o vetor, nosso WHILE deve continuar enquanto o endereço de nosso ponteiro for diferente último endereço do vetor (que não precisará ser acessado, pois cada iteração do looping calcula o próximo termo da PA).

Em seguida, usamos o laço FOR para você ver como podemos manipular ponteiros dentre dele também.
Inicializamos, novamente, o ponteiro a partir do primeiro elemento: ptr = pa;
Depois, imprimimos todos os elementos, enquanto o endereço que o ponteiro aponta for menor ou igual ao último endereço do vetor.

Veja como ficou nosso código:


#include <stdio.h>
// Curso C Progressivo: www.cprogessivo.net
// O melhor curso de C! Online e gratuito !
// Artigos, apostilas, tutoriais e vídeo-aulas sobre
// a linguagem de programação C !
 
int main(void)
{ int pa[10], razao; int *ptr; printf("Insira o termo inicial da PA: "); scanf("%d", &pa[0]); ptr = pa; printf("Insira razao da PA: "); scanf("%d", &razao); while( ptr != &pa[9]) { *(ptr+1) = *ptr + razao; ptr++; } for(ptr = pa ; ptr <= &pa[9] ; ptr++) printf("-> %d ", *ptr);

    return 0;
}


 Na próxima seção, vamos usar todos esses conceitos sobre ponteiros com bastante frequência.

4 comentários:

Anônimo disse...

Na seção onde diz:
ptr – 3 -> endereço de onde ptr apontava, deslocado de duvas variáveis para trás

o correto seria: ptr – 3 -> endereço de onde ptr apontava, deslocado de três variáveis para trás?

Paulo Freitas disse...

Muito bom, Parabéns. Agora consigo ler os trechos de código em C q contém ponteiros e entende-los, antes não entendia nada, confundia *ptr (declaração de ponteiro) com *ptr (extrair valor da memória para onde o ponteiro aponta.
Obrigado a toda e equipe do C Progressivo.!

Unknown disse...

Fiz a seguinte alteração no código mudando o 'while' para um laço 'for'. Mas parece que o que retornou foram os endereços de memória.
--------------------------------------

int main(void)

{
int pa[100], razao;

int *ptr;

printf("Insira o termo inicial da PA: ");
scanf("%d", &pa[0]);

ptr = pa;

printf("Insira razao da PA: ");
scanf("%d", &razao);

for(ptr =&pa[0]; ptr <= &pa[99]; ptr+=1)
{
*(ptr+1) = *ptr + razao;

printf("-> %d ", *ptr);

ptr++;
}


system("pause");


return 0;
}

A saída foi essa:

Insira o termo inicial da PA: 5
Insira razao da PA: 7
-> 5 -> 1999976654 -> 1999976618 -> 0 -> 3872520 -> 127 -> 1375732051 -> 1 -> 3866960 -> 3866624 -> 3872531 -> 3866960 -> 16777218 -> 2 -> 2000253429 -> -2 -> 1999977726 -> 1375732051 -> 3872528 -> 8 -> 1999895274 -> -1 -> 2686648 -> 0 -> 4199152 -> 0 -> 0 -> 16842752 -> 7536836 -> 3870328 -> 2686664 -> 3866624 -> 1972040841 -> 1719536184 -> 3870328 -> 2000031890 -> 36 -> 4 -> -2029387870 -> 1972041216 -> 0 -> 2686684 -> 1972634280 -> 1972040914 -> 1972048270 -> 332126055 -> 0 -> 4199152 -> -1 -> 1972145365
Pressione qualquer tecla para continuar. . .

Porque saíram os endereços de memória uma vez que eu escrevi para que me dê na saída um VALOR ?? *ptr ?? (asterisco antes do ponteiro) --
printf("-> %d ", *ptr);


Anônimo disse...

O blog de vocês me ensina mais do que as aulas do meu professor de Algoritmos e Estruturas de Dados 1. Obrigado.

Gostou desse tutorial de C?
Sabia que o acervo do portal C Progressivo é o mesmo, ou maior que, de um livro ou curso presencial?
E o melhor: totalmente gratuito.

Mas para nosso projeto se manter é preciso divulgação.
Para isso, basta curtir nossa página no Facebook e/ou clicar no botão +1 do Google.
Contamos e precisamos de seu apoio.