Programação de Computadores I – Ponteiros Profa. Mercedes Gonzales Márquez Ponteiros - Manipulação Declaração: <tipo> *<identificador> int *p; float *q; O operador unário & captura o endereço de um objeto. p = &x; O operador unário * é um operador de indireção: quando aplicado a um apontador, acessa o conteúdo do objeto apontado. x = *p; Ponteiros - Manipulação int vet[4]; vet aponta para vet[0] (vet[0]==*vet) e - vet+1 aponta para vet[1] e *(vet+1) refere-se ao conteúdo de vet[1] – vet+i aponta para vet[i] e *(vet+i) refere-se ao conteúdo de vet[i] Ponteiros - Manipulação int vet[4]; int *pa; pa = &vet[0]; pa vet Se pa aponta para vet[0], então: - pa+1 aponta para vet[1] e pa+i aponta para vet[i]. Aritmética de ponteiros Todas as operações sobre ponteiros levam em conta o tamanho do tipo apontado . Operações válidas de ponteiros: – – – – – Atribuição entre ponteiros do mesmo tipo Adição/Subtração entre um ponteiro e um inteiro. Comparação entre dois ponteiros que apontam a elemntos do mesmo array. Subtração entre dois ponteiros que apontam a elementos do mesmo array. Atribuição ou comparação com zero (NULL) Aritmética de Ponteiros Incremento/decremento: Se p é um ponteiro a tipo T, p++ incrementa o valor de p em sizeof(T) (onde sizeof(T) é a quantidade de armazenagem necessária para um dado de tipo T). Similarmente, p-- decrementa p em sizeof(T); T tab[N]; T * p; int i; p=&tab[i]; p++; // p contem o endereço de tab[i+1]; Aritmética de Ponteiros Adição/subtração com um inteiro: Se p é um ponteiro a tipo T e n é um inteiro, p+n incrementa o valor de p em n*sizeof(T). Similarmente, p-n decrementa p em n*sizeof(T); T tab[N]; T * p; p=tab; p=p+n; // p contem o endereço de tab[n]; Aritmética de Ponteiros Comparação de dois ponteiros. – Se p e q aponta a membros do mesmo array, então são válidas as relações como ==, !=, <, >=, etc. Por exemplo, p<q é verdade se p aponta a um elemento anterior do array que q aponta. Subtração de ponteiros: – Se p e q apontam a elementos do mesmo array, e p<q, então q-p+1 é o número de elementos de p até q inclusive. O comportamento é indefinido para aritmética ou comparação com ponteiros que não apontam a membros do mesmo array. Examplo de subtração de ponteiros /* strlen: returna o comprimento da string s */ int strlen(char *s){ char *p = s; while (*p != '\0') p++; return p - s; } Ponteiros e strings char a[] = “aprendendo ponteiros"; /* um array */ char *p = “aprendendo ponteiros"; /* um ponteiro */ a aprendendo ponteiros\0 p aprendendo ponteiros\0 a é um array, apenas do tamanho suficiente para armazenar a sequência de caracteres e '\0. p é um ponteiro inicializado para apontar uma string constante; Ponteiros - Exercícios int x=3, y=5, *p=&x, *q=&y, *r; double z; Expressão p==&x **&p r=&z 7**p/*q+7 *(&y)*=*p Valor 1 3 erro 11 15 Ponteiros Exemplo O que será impresso pelo programa abaixo considerando que os valores lidos nas variáveis x e y sejam 2 e 5,respectivamente? Ponteiros Exemplo O que será impresso pelo programa abaixo considerando que os valores lidos nas variáveis x e y sejam 2 e 5,respectivamente? Ponteiros Exemplo O que faz o trecho de programa abaixo? Ponteiros para registros Ao criarmos uma variável de um tipo struct, esta e armazenada na memoria como qualquer outra variável, e portanto possui um endereço. Exemplo #include <stdio.h> typedef struct { double x; double y; } Coordenada; int main(){ Coordenada c1, c2, *c3; c3 = &c1; Ponteiros para registros Para acessarmos os campos de uma variavel struct via um ponteiro, podemos utilizar o operador * juntamente com o operador . como de costume: Coordenada c1, *c3; c3 = &c1; (*c3).x = 1.5; (*c3).y = 1.5; Em C também podemos usar o operador -> para acessar campos de uma estrutura via um ponteiro. Podemos obter o mesmo resultado do exemplo anterior: Coordenada c1, *c3; c3 = &c1; c3->x = 1.5; c3->y = 1.5; Ponteiros para registros Resumindo: Para acessar campos de estruturas via ponteiros use um dos dois: ponteiroEstrutura->campo (*ponteiroEstrutura).campo Exercício 1: Vamos criar as seguinte funcões: void leCoordenada3D(Coordenada3d *f);: lê dados de uma ponto no espaço tridimensional com coordenadas (x,y,z) passada como ponteiro. (Por quê como ponteiro?) void imprimeCoordenada3D(Coordenada3d f); Imprime coordenadas de um ponto. O programa principal que requeira a leitura de 5 pontos no espaço tridimensional. Ponteiros para registros Coordenada3d ProdutoEscalar(Coordenada3d v1,Coordenada3d v2) onde produto_escalar=<v1,v2>=v1.x*v2.x+v1.y*v2.y Alocação dinámica função malloc – Parâmetro: tamanho desejado, em bytes – Resultado: apontador para espaço na memória Programa int *p; p = (int*)malloc(4); *p = 5; printf("%d", *p); Alocação dinámica função free: – Parâmetro: endereço já alocado – Resultado: libera a área alocada Programa int *p; p = (int*)malloc(4); *p = 5; free(p); Alocação dinámica função sizeof: sizeof(variavel) – Retorna quantidade de memória ocupada pela variável sizeof(tipo) – Retorna quantidade de memória ocupada por uma variável com este tipo. VETOR DINÂMICO • Calcular tamanho do vetor com sizeof • Reservar memória com malloc • Acessar elementos com [ ] ou ponteiros • Liberar memória do vetor com free Alocação dinámica Exemplo: Alocação dinámica de um vetor #include <stdio.h> #include <stdlib.h> int main(void) { int n; int * vet; int i; printf("Input number of elements: \n"); scanf("%d", &n); if ((vet=(int *)malloc(n * sizeof(int)))==NULL) { printf(“Erro de alocação de memoria !\n"); exit(1); } for (i=0; i<n; i++) scanf("%d", &vet[i]); for (i=0; i<n; i++) printf("%d ", vet[i]); free(vet); } Alocação dinámica de strings void main(void) { char sir1[40]; char *sir2; printf(“Informe uma string: \n"); scanf("%40s", sir1); if ((sir2=(char *)malloc(strlen(sir1)+1))==NULL) { printf(“Erro na alocação de memória !\n"); exit(1); } strcpy(sir2, sir1); printf(“A cópia e: %s \n", sir2); .......... } Alocação dinámica Exercício 2. O exercício 1 pedia para ingressar 5 pontos do espaço tridimensional, agora considere um vetor de pontos de tamanho dinâmico. Exercícios Exercício 3. O que será impresso pelo programa abaixo: #include <stdio.h> typedef struct{ int x; int y; } T; void f1(T *a){ f2(&(a->x)); f2(&(a->y)); } void f2(int *b){ *b = 2*(*b); Exercícios int main(){ T a, b, *c, *d; c = &a; a.x = 2; a.y = 4; b.x = 2; b.y = 2; d = c; f1(d); b = *d; printf("x: %d --- y: %d\n",b.x,b.y); } Função que retorna um ponteiro int * soma_vetor4(int *a, int *b, int n) { int * r; r=(int *) malloc(sizeof (int) * n); if (r==NULL) exit(1); int i; for (i=0; i<n; i++, a++, b++) r[i]=*a+*b; return r; } … int a[3]={1,2,3}; int b[3]={4,5,6}; int * rr; rr=soma_vetor4(a,b,3); imprime_vetor(rr,3);