DAS5102 – Fundamentos da Estrutura da Informação
Ponteiros e Arrays
Ponteiros são fundamentais para a programação bem sucedida em C:
•
•
•
Passagem de parâmetros por referência;
Alocação dinâmica de memória;
Aumentar a eficiência de certar rotinas.
Essencialmente, um ponteiro nada mais é do que uma variável que ao invés de conter um
valor, contém um endereço de memória.
O conceito de utilizar espaço em memória não é em absoluto novo. De fato, linguagens de
máquina utilizam tal conceito todo o tempo.
ADD A,@RI
Exemplo 1 – mnemônico (Intel 80C51) que executa a soma do conteúdo da RAM interna apontada por Ri ao
Acumulador.
Declaração de Ponteiros
<tipo> *<nome_variável>
int
*iptr;
float *fptr;
char *cptr;
Exemplo 2 – exemplo da declaração de diversos ponteiros
Como um ponteiro armazena um endereço de memória e não um valor específico, pode
parecer estranho a primeira vista que seja requerida a associação de um tipo ao se declaram
um ponteiro. No entanto, muito comumente, deseja-se acessar o valor armazenado pela
variável apontada por um ponteiro. Desta forma, o tipo do ponteiro serve para instruir o
compilador na maneira pela qual o dado apontado será acessado. Essencialmente, o tipo de
dados e a c
odificação do dado (como os bits serão interpretados, necessário por exemplo para tipos com
base na notação de ponto flutuante).
Operadores de Ponteiros
•
“*” conteúdo: aplicado a um variável tipo ponteiro, retorna o conteúdo do endereço
apontado pelo ponteiro;
•
“&” endereço: aplicado a uma variável, retorna seu endereço de memória.
Daniel Duarte Abdala
1
DAS5102 – Fundamentos da Estrutura da Informação
int count;
int *iptr;
iptr = &count;
printf(“%d”, *iptr);
Exemplo 3 – exemplo da utilização de ambos os operadores unários
Inicialização de Ponteiros
•
•
•
Ponteiros são inicializados ao definirmos um endereço para o qual eles devem
apontar.
Ponteiros não inicializados são também chamados de “ponteiros selvagens”
A não inicialização de ponteiros é um dos principais fatores para erros em tempo de
execução em programas escritos na linguagem C. Tais erros são difíceis de identificar e
corrigir, porque o tempo decorrido entre o acesso ilegal à memória de um ponteiro e a
efetiva ocorrência do erro é imprevisível.
Uma maneira de garantir que um ponteiro declarado não apontará para um lugar qualquer da
memória é atribuir o valor NULL para o mesmo.
int *iptr = null;
Ponteiros e Arrays
Ponteiros são muito utilizados para a navegação de arrays, principalmente de arrays alocados
de maneira dinâmica. A idéia geral é alocar o array usando ou o método estático ou o dinâmico
e então criar uma variável do tipo ponteiro que apontará para a primeira posição do ponteiro.
Utilizando aritmética de ponteiros (incremento, decremento, saltos) é possível percorrer o
array sem ter que se preocupar com quantos bytes devem ser acessados, pois a tipagem do
ponteiro cuidará deste detalhe.
00H
Vet[0]
02H
Vet[1]
04H
Vet[2]
06H
Vet[3]
08H
Vet[4]
0AH
Vet[5]
0CH
Vet[6]
Figura 1 – Exemplo de posicionamento de um array na memória
É importante ressaltar que a utilização de ponteiros para indexação de arrays apresenta um
risco intrínseco. Como C não é uma linguagem fortemente tipada, arrays não possuem um
marcador de fim de alocação de memória tal como acontece em PASCAL. Ponteiros permitirão
Daniel Duarte Abdala
2
DAS5102 – Fundamentos da Estrutura da Informação
que a memória continue sendo acessada seqüencialmente mesmo após o final da área
previamente alocada para o array tenha sido toda percorrida.
Aritmética de Ponteiros
Uma das grandes vantagens decorrentes da utilização de ponteiros é a possibilidade de
indexar posições de memória de maneira fácil e intuitiva. Tal endereçamento é alcançado a
partir de operações aritméticas simples que tem como objetos variáveis do tipo ponteiro.
Operandos unários:
•
•
++ incremento unitário;
-- decremento unitário.
Suponha que p é um ponteiro do tipo inteiro e suponha que o tipo inteiro na arquitetura de
destino do exemplo sejam representados por 2 bytes cada. Considere o seguinte trecho de
código:
int vet[10];
int *iptr;
iptr = vet;
iptr++;
Exemplo 4 – navegação de arrays usando ponteiros
Assumindo que o array “vet” seja alocado pelo “loader” do sistema operacional iniciando na
posição 00H, iptr erá apontar para a posição 00H inicialmente. Ao se executar a operação
iptr++, o endereço apontado por iptr será incrementado em uma unidade, o que
corresponderá, dado o fato de que inteiros são representados por dois bytes, ao endereço
02H. (veja figura1 para exemplo)
Comparação de Ponteiros
O ponto importante a respeito da comparação de ponteiros a ser considerado diz respeito a
semântica da comparação. Como ponteiros são variáveis que contém endereços de memória,
ao compararmos ponteiros o que estamos fazendo realmente é verificando se dois endereços
de memória são idênticos ou não.
A primeira vista, tal tipo de comparação pode parecer de pouca importância, no entanto ela
será de grande valor futuramente quando ponteiros forem utilizados para manipular
estruturas de dados complexas tal como listas ligadas ou árvores.
Podemos comparar se dois ponteiros são iguais menores ou maiores exatamente como se
compararam valores de variáveis.
Daniel Duarte Abdala
3
DAS5102 – Fundamentos da Estrutura da Informação
int vet[7];
int *iptr1, *iptr2;
iptr1
iptr2
iptr1
iptr1
iptr1
iptr1
= &vet[0];
= &vet[6];
== iptr2;
< iptr2;
> iptr2;
<= iptr2;
Exemplo 5 – comparação de ponteiros
Daniel Duarte Abdala
4
DAS5102 – Fundamentos da Estrutura da Informação
Lista de Exercícios
1. O que á de errado com o programa abaixo? Como poderíamos corrigi-lo?
void main( void )
{
int x, *p;
x = 10;
*p = x;
}
2. Seja o seguinte trecho de programa:
int i = 3, j = 5;
int *p, *q;
p = &i;
q = &j;
Qual será o valor das seguintes expressões:
a)
b)
c)
d)
p==&i;
*p - *q;
&p==&i;
3* *p/(*q)+7
3. Qual será a saída do programa supondo que i ocupa o endereço 4094H na memória?
int main( void )
{
int i=5, *p;
p=&i;
printf(“%d %d %d %d %d\n”, p, *p+2, **&p, 3**p, **&p+4);
}
4. Assumindo que Pulo[] é um array do tipo int, quais das seguintes expressões
referenciam o valor do terceiro elemento do array?
a) *(pulo+2)
b) *(pulo+4)
c) pulo+4
d) pulo+2
5. Suponha a declaração:
Daniel Duarte Abdala
5
DAS5102 – Fundamentos da Estrutura da Informação
int mat[4], *p, x;
Quais das expressões abaixo são válidas? Justifique:
a)
b)
c)
d)
p = mat+1;
p = mat++;
p = ++mat;
x = (*mat)++;
6. Explique a diferença entre os comandos abaixo: (assuma que p é um ponteiro do tipo
int)
a) p++;
b) (*p)++;
c) *(p++);
7. Explique o programa abaixo. Encontre o erro, corrija-o para que o mesmo escreva o
número 10 na tela.
#include <stdio.h>
int main( void )
{
int x, *p, **p;
p = &x;
q = &p;
x = 10;
printf(“\n%d\n”, &q);
return ( 0 );
}
Daniel Duarte Abdala
6
Download

Ponteiros e Arrays