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.)