Ponteiros em C – Aritmética de Ponteiros

Aritmética de Ponteiros

Na lição anterior definimos o que são ponteiros, como declará-los e como realizar sua atribuição. Vamos agora abordar a aritmética de ponteiros em linguagem C.

Há duas operações aritméticas que podemos efetuar com ponteiros: adição de ponteiros e subtração de ponteiros. Além disso, também é possível comparar dois ponteiros entre si.

Suponha dois ponteiros, pont1 e pont2. pont1 aponta para um inteiro de 16 bits, cujo endereço é 5000. Vamos incrementar esse ponteiro (somar uma posição a ele) por meio do operador de incremento ++:

pont1++;

Qual será o valor contido em pont1 agora? 

O valor em pont1 será o endereço 5002, e não 5001, como era de se esperar por conta do incremento, pois sempre que um ponteiro é incrementado (ou decrementado), ele irá apontar para a posição de memória do próximo elemento de seu tipo (ou para a posição anterior, no caso do decremento).

Como um inteiro de 16 bits possui 2 bytes, o valor dese ponteiro é incrementado em duas unidades, e não em apenas uma. Já ponteiros de caractere sempre são incrementados ou decrementados em uma unidade, coo na aritmética normal, pois caracteres ocupam apenas um byte na memória.

Ou seja, a aritmética de ponteiros é baseada em seu tipo declarado.

Da mesma forma, se usarmos um ponteiro de inteiro de 32 bits, ao incrementá-lo seu endereço (no exemplo) passará a ser o endereço 5004, 4 "unidades" à frente, pois 32 bits equivalem a 4 bytes (32 / 8 bits).

Portanto, a aritmética de ponteiros lida com os endereços apontados por eles, e não com o conteúdo das variáveis apontadas. Fique atento a esse detalhe!

Tamanho de uma variável ponteiro

O tamanho de uma variável é um aspecto muito importante para o programador. Precisamos saber quanto espaço na memória uma variável ocupa quando é utilizada, para que seja possível escrever programas enxutos e que executem com boa performance. Isso é particularmente importante quando desenvolvemos programas para dispositivos embarcados, os quais, no geral, contam com quantidade restrita de memória disponível.

Dependendo da plataforma, uma variável pode ter tamanhos que variam de 8 a 64 bits. Por exemplo, em uma plataforma de 32 bits, uma variável do tipo int ocupará o espaço de 4 bytes (32 / 8 = 4).

O código a seguir nos permite verificar o tamanho na memória utilizado por ponteiros de diferentes tipos, usando o operador sizeof:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main()
{
 setlocale(LC_ALL, "");
 char caractere;
 int inteiro;
 double duplo;
 int *inteiro_ptr;
 char *caractere_ptr;
 double *duplo_ptr;
 caractere_ptr = &caractere;
 inteiro_ptr = &inteiro;
 duplo_ptr = &duplo;
 printf("Tamanho de um ponteiro de inteiro = %d valor = %p\n", sizeof(inteiro_ptr),inteiro_ptr);
 printf("Tamanho de um ponteiro de char = %d valor = %p\n", sizeof(caractere_ptr),caractere_ptr);
 printf("Tamanho de um ponteiro de double = %d valor = %p\n", sizeof(duplo_ptr),duplo_ptr);
 return 0;
}

A tabela a seguir mostra os tamanhos típicos de tipos de dados, em bytes, encontrados na maioria dos sistemas:

Tipo de dado Tamanho em bytes
byte 1
char 1
short 2
int 4
long 8
float 4
double 8

Adição e subtração em ponteiros

Tomemos como exemplo a expressão a seguir:

pont1 = pont1 + 40;

Essa declaração faz com que o ponteiro pont1 passe a apontar para o quadragésimo elemento do tipo declarado para o ponteiro a partir da posição apontada atualmente por ele. A mesma ideia se aplica à subtração de ponteiros, porém obviamente com o ponteiro apontando para posição anterior na memória RAM do sistema.

Note que a nova posição (quadragésimo elemento no exemplo) depende do tipo declarado no ponteiro. Por exemplo, para um ponteiro de inteiro de 32 bits isso significa 40 posições x 4 bytes = 160 posições à frente (A0 em hexadecimal).

Não podemos efetuar outras operações com ponteiros além da adição e subtração, com multiplicação e divisão, e nem podemos usar operadores de deslocamento bit a bit.

Vejamos um código de exemplo que mostra as operações de adição e subtração de ponteiros:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

int main()
{
 setlocale(LC_ALL, " ");
 int a;
 a = 30;
 int *pont1;
 pont1 = &a;
 printf("Endereço de a: %p\n", pont1);
 pont1++;
 printf("Endereço do ponteiro incrementado: %p\n", pont1);
 pont1 = pont1 + 10;
 printf("Somando 40 ao ponteiro pont1: %p\n", pont1);
 pont1--;
 printf("Decrementando o ponteiro: %p\n", pont1);
 return 0;
}

Podemos ver o resultado da execução desse código na figura a seguir:

Aritmética de ponteiros em linguagem C

Inicialmente, podemos ver que o ponteiro pont1 apontava para o endereço de memória 0x0060FF08 (expresso em hexadecimal), onde se localiza a variável a criada.

Após o incremento (pont1++), ele passa a apontar para a posição xFF0C, que se encontra C - 8 = 4 endereços à frente da posição inicial; lembre-se de que temos aqui um inteiro de 32 bits (32 / 8 = 4).

Então, somamos 10 ao ponteiro (pont1 = pont1 + 10), que passa a apontar para o endereço xFF34. Note que, em hexadecimal,  34 - 0C = 28, que convertido para decimal é igual a 10.

E, finalmente, decrementamos o ponteiro (pont1--), que finaliza apontando para o endereço de memória xFF30, 4 posições a menos do que no comando anterior.

Comparação de Ponteiros

Podemos efetuar a comparação de ponteiros usando os operadores de comparação padrão - apesar de esta técnica não ter tanta utilidade na prática.

O código a seguir mostra a comparação entre ponteiros:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main()
{
 setlocale(LC_ALL, "");
 int vetor[] = {10, 30, 20};
 int *p0 = vetor;
 int *p1 = vetor + 1;
 int *p2 = vetor + 2;
 int *p3 = p2;
 printf("p2 > p0: %d\n", p2 > p0);
 printf("p0 > p1: %d\n", p0 > p1);
 printf("p2 < p0: %d\n", p2 < p0);
 printf("p3 = p2: %d\n", p3 == p2);
 return 0;
}

O resultado mostrado será o valor 1 para comparação verdadeira e 0 para comparação falsa, como podemos ver na figura a seguir:

Comparação de Ponteiros em C

Anterior: Ponteiros em C - Introdução

Próxima lição: Indireção múltipla de ponteiros

 

Sobre Fábio dos Reis (1182 Artigos)
Fábio dos Reis trabalha com tecnologias variadas há mais de 25 anos, tendo atuado nos campos de Eletrônica, Telecomunicações, Programação de Computadores e Redes de Dados. É um entusiasta de Unix, Linux e Open Source em geral, adora Eletrônica e Astronomia, e estuda idiomas, além de ministrar cursos e palestras sobre diversas tecnologias em São Paulo e outras cidades do Brasil.
Contato: Website

2 Trackbacks & Pingbacks

  1. Ponteiros em C - uma introdução - Bóson Treinamentos em Tecnologia
  2. Ponteiros em C - Indireção Múltipla - Bóson Treinamentos em Tecnologia

Escreva um comentário

Seu e-mail não será divulgado


*