Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original
Ponteiros –
Parte2
Vetores como Ponteiros
(recordando)
O identificador do vetor é um ponteiro constante
– Exemplo: float v[ ] = {1.3,2.2,3.1,8.4};
&v[0] e v são iguais: acessam o mesmo endereço
de memória.
v[0] e *v são iguais: acessam o conteúdo da mesma
posição de memória.
Portanto, podemos dizer que:
v[i] é o mesmo que *(v+i)
&v[i] é o mesmo que v+i
Vetores como Ponteiros
(recordando)
Suponha a seguinte declaração:
char s[] = “Ola Mundo”;
char *p = s; /* p recebe &s[0] */
Algumas formas de acessar o caractere ‘a’ presente
na string:
1) s[2] – acesso direto ao elemento da posição de
índice 2
2) *(p+2) - acesso indireto ao elemento da posição
de índice 2
3) *(s+2) – se s == &s[0], pode-se usar a mesma
estratégia anterior
Passagem de Vetores para Funções
Ao invocar uma função passando um vetor
como parâmetro, esta na realidade não
receberá o vetor na sua totalidade, mas
apenas o seu endereço inicial.
Se o endereço do vetor é passado para a
função, então a variável que receberá esse
endereço deve ser um ponteiro.
Exemplo 1
#include <stdio.h>
int strlen(char *s)
{ char *p = s;
while(*s != ‘\0’)
s++;
return (int) (s-p);
}
main()
{ char nome[100];
printf(“Digite uma string:”);
gets(nome);
printf(“\nTamanho da string: %d”, strlen(nome));
}
Matrizes como Ponteiros
Ao declarar uma matriz, o compilador C calcula o
tamanho em bytes necessário para armazenar essa
matriz. Por exemplo:
tipo_da_variável nome_da_variável [tam1][tam2] ...
[tamN];
Esse tamanho é igual a:
tam1 x tam2 x tam3 x ... x tamN x tamanho_do_tipo
O compilador então aloca esse número de bytes em
um espaço livre de memória. O nome da variável
declarada é, na verdade, um ponteiro para o tipo
da variável da matriz.
Matrizes como Ponteiros (cont.)
Tendo alocado na memória o espaço para a
matriz, o compilador toma o nome da
variável (que é um ponteiro) e aponta para o
primeiro elemento da matriz.
Atenção: a memória é linear. Assim, do
ponto de vista de armazenamento, não há
diferença entre matriz e vetor, pois os
elementos são consecutivos na memória.
Matrizes como Ponteiros (cont.)
Veremos agora um dos usos mais importante
dos ponteiros:
varredura sequencial de uma matriz.
É possível varrer todos os elementos de uma
matriz de forma sequencial, usando um ponteiro
que será incrementado.
Matrizes como Ponteiros (cont.)
Exemplo: Varredura sequencial de matriz
int main ()
{ int m[50][50], cont, *p;
p = m[0]; /* atribui a p o endereço do elemento
inicial da matriz m*/
for(cont=0; cont<2500; cont++)
{ *p = cont + 1;
printf("\n%d", *p);
p++;
}
}
Uma única estrutura
de repetição é
suficiente!
Matrizes como Ponteiros (cont.)
Outra forma de varrer uma matriz (sem uso
de ponteiros):
int main ()
{ int m [50][50], i, j;
for (i=0;i<50;i++)
for (j=0;j<50;j++)
m[i][j]=0;
}
Matrizes como Ponteiros (cont.)
Qual a desvantagem da varredura não
sequencial (sem uso de ponteiros)?
Resp. Cada vez que se faz m[i][j], o programa tem que
calcular o deslocamento que será dado ao ponteiro. Ou
seja, o programa tem que calcular 2500
deslocamentos. Na varredura sequencial, o único
cálculo que deve ser feito é o incremento do ponteiro.
Fazer 2500 incrementos em um ponteiro é muito mais
rápido que calcular 2500 deslocamentos completos!!!
Atenção: Há uma diferença entre o nome de um vetor e um ponteiro:
um ponteiro é uma variável, enquanto o nome de um vetor não é
uma variável e sim uma constante!
Deslocamento de Elementos
Como é feito esse deslocamento afinal?
No caso de Vetor, o índice determina o
deslocamento do elemento a partir do seu início. Por
exemplo:
int vet[5];
vet[i] estará na posição (início_de_vet + i). Ou seja:
(vet + i)
No caso de Matriz, o deslocamento em relação ao
início, é uma função dos vários índices da matriz,
que transforma todos os seus índices em um só, ou
seja, é a linearização dos vários índices.
Deslocamento de Elementos (cont.)
Exemplo: int mat[10][10];
– mat[1][2] é o 12º elemento, ou seja, (1*10+2)º. O 1º
elemento é o 0º.
– mat[2][3] é o 23º elemento, ou seja, (2*10+3)º.
– mat[9][5] é o 95º elemento, ou seja, (9*10+5)º.
Para matriz bidimensional (com dois índices):
– Se mat é uma matriz com primeiro e segundo
índice de valor máximo d1 e d2 (ex. int mat[d1][d2]),
respectivamente, o elemento mat[i][j] estará na
posição:
(inicio de mat) + i * d2 + j
Deslocamento de Elementos (cont.)
Para matriz tridimensional (com 3 índices):
– Se mat é uma matriz com primeiro, segundo e
terceiro índice de valor máximo d1, d2 e d3 (ex. int
mat[d1][d2][d3]), respectivamente, o elemento
mat[i][j][k] estará na posição:
(inicio de mat) + i * d2 * d3 + j * d3 + k
Nota: Observe que para acessar um elemento é necessário conhecer o tamanho de cada dimensão da matriz, exceto da
primeira. Por essa razão, ao declarar uma matriz como parâmetro
formal de uma função é necessário informar o tamanho de todas
as dimensões a partir da segunda.
Exemplo: void soma_matrizes(int x[][50], int y[][50], int z[][50]);
Strings
Seguindo o mesmo raciocínio anterior,
nomes de strings são do tipo char*.
Isto nos permite escrever nossa própria
função StrCpy(), que funcionará de forma
semelhante à função strcpy() da biblioteca
string.
Strings (cont.)
void StrCpy (char *destino, char *origem)
{ while (*origem)
{ *destino=*origem;
origem++;
destino++;
}
*destino='\0';
}
int main ()
{ char str1[100], str2[100], str3[100];
printf ("Entre com uma string: ");
gets (str1);
StrCpy (str2,str1);
StrCpy (str3,"Voce digitou a string ");
printf ("\n\n%s%s",str3,str2);
}
Critério de parada: string
termina com '\0'
Atenção: as instruções
origem++ e destino++
não alteram o valor do
ponteiro-base da string,
pois em C são passadas
para as funções apenas
cópias dos argumentos.
Ponteiros como Vetores
Se o nome de um vetor é um ponteiro
constante e podemos indexar o nome de um
vetor, portanto: também podemos
indexar um ponteiro qualquer!
Ponteiros como Vetores
int main ()
{ int v [10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, *p;
p=v;
printf ("O terceiro elemento do vetor e:
%d",p[2]); /* p[2] equivale a *(p+2) */
}
Ponteiros para Ponteiros
Podemos declarar um ponteiro para um ponteiro
com a seguinte notação:
– tipo_da_variável **nome_da_variável;
Algumas considerações:
– **nome_da_variável acessa o conteúdo final
da variável apontada;
– *nome_da_variável acessa o conteúdo do
ponteiro intermediário.
Ponteiros para Ponteiros (cont.)
Em C podemos declarar ponteiros para ponteiros
para ponteiros, ou então, ponteiros para ponteiros
para ponteiros para ponteiros, e assim por diante.
Para fazer isso basta aumentar o número de
asteriscos na declaração. Para acessar o valor
desejado apontado por um ponteiro para ponteiro,
o operador asterisco deve ser aplicado duas
vezes (veja no exemplo a seguir).
Exemplo 2
#include <stdio.h>
main()
{
float pi = 3.1415, *pf, **ppf;
pf = π
ppf = &pf;
printf(“\n%.4f", **ppf);
printf(“\n%.4f", *pf);
}
Importante!
O Ministério da Saúde adverte: o uso
descuidado de ponteiros pode levar a sérios
bugs e a dores de cabeça terríveis!!!
Exercícios
1) Verifique o programa abaixo. Encontre o(s)
seu(s) erro(s) e corrija-o(s) para que o mesmo
escreva o número 10 na tela.
#include <stdio.h>
int main()
{
int x, *p, **q;
p = *x;
q = &p;
x = 10;
printf("\n%d\n", &q);
}
Exercícios (cont.)
2) Implemente uma função que receba por parâmetro
uma matriz a de nxm elementos, um vetor b de m
elementos e devolve um vetor c de n elementos que
representa a multiplicação de a por b. Use ponteiros
para referenciar os elementos da matriz e dos
vetores.
Ex. de protótipo da função:
void mult_mat_vet(float *a, float *b, float *c, int n,
int m)
Exercícios (cont.)
3- Implemente uma função que receba por
parâmetro dois vetores x e y de tamanhos n
e m, respectivamente, e devolve um vetor c
de p elementos que representa o conjunto
união entre x e y (isto é, os elementos que
estão em x ou em y). Use ponteiros para
referenciar os elementos dos vetores.
Exercícios (cont.)
4- Implemente uma função que receba por
parâmetro dois vetores x e y de tamanhos n
e m, respectivamente, e devolve um vetor c
de p elementos que representa o conjunto
interseção entre x e y (isto é, os elementos
que estão em x e em y). Use ponteiros para
referenciar os elementos dos vetores.
Exercícios (cont.)
5- Faça as funções StrLen() e StrCat() que
funcionem como as funções strlen() e strcat()
de string.h, respectivamente. Use ponteiros
para referenciar os elementos dos vetores.
Obs: você não deve usar as funções
strlen() e strcat() já prontas.
�Ponteiros – �Parte2�
Vetores como Ponteiros (recordando)
Vetores como Ponteiros (recordando)
Passagem de Vetores para Funções
Exemplo 1
Matrizes como Ponteiros
Matrizes como Ponteiros (cont.)
Matrizes como Ponteiros (cont.)
Matrizes como Ponteiros (cont.)
Matrizes como Ponteiros (cont.)
Matrizes como Ponteiros (cont.)
Deslocamento de Elementos
Deslocamento de Elementos (cont.)
Deslocamento de Elementos (cont.)
Strings
Strings (cont.)
Ponteiros como Vetores
Ponteiros como Vetores
Ponteiros para Ponteiros
Ponteiros para Ponteiros (cont.)
Exemplo 2
Importante!
Exercícios
Exercícios (cont.)
Exercícios (cont.)
Exercícios (cont.)
Exercícios (cont.)