Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original
Linguagem de Programação Estruturada I Lucas Ferrari de Oliveira Professor Adjunto Universidade Federal do Paraná Ponteiros 2 Prof. Lucas Ferrari de Oliveira Sumário Conceitos Utilidades dos Ponteiros Operadores para Ponteiros: Operador & Operador * Declarando Ponteiros Expressões com Ponteiros Atribuições de Ponteiros Aritmética de Ponteiros Comparação entre ponteiros Ponteiros e Matrizes Indireção Múltipla Ponteiro Nulo Funcao com ponteiros 3 Prof. Lucas Ferrari de Oliveira Ponteiros Conceitos:Conceitos: Um ponteiro é o endereço de uma variável na memória. Uma variável de ponteiro é uma variável especialmente declarada para guardar um ponteiro para seu tipo especificado. 4 Prof. Lucas Ferrari de Oliveira Ponteiros Utilidades dos PonteirosUtilidades dos Ponteiros São uma maneira rápida de referenciar uma variável em C; São o meio pelo qual as funções em C conseguem modificar seus parâmetros de chamada; Provêem suporte às listas encadeadas e outras estruturas de dados dinâmicas. 5 Prof. Lucas Ferrari de Oliveira Ponteiros Operadores para PonteirosOperadores para Ponteiros operador &: Operador unário; Devolve o endereço da memória em que se encontra alocado seu operando; Exemplo: m = &count; atribui a m o endereço da memória em que se encontra a variável count. Esse endereço não tem nenhuma relação com o valor de count. 6 Prof. Lucas Ferrari de Oliveira Ponteiros Operadores para PonteirosOperadores para Ponteiros operador &: Operador unário; Devolve o endereço da memória em que se encontra alocado seu operando; Exemplo: m = &count; atribui a m o endereço da memória em que se encontra a variável count. Esse endereço não tem nenhuma relação com o valor de count. Pode-se imaginar & como significando “o endereço de”. Desta forma, a sentença de atribuição significa “m recebe o endereço de count”. Pode-se imaginar & como significando “o endereço de”. Desta forma, a sentença de atribuição significa “m recebe o endereço de count”. 7 Prof. Lucas Ferrari de Oliveira Ponteiros Operadores para PonteirosOperadores para Ponteiros operador &: Exemplo mais concreto, em termos de memória: assuma que a variável count foi alocada para a posição de memória 2000. Assuma também que count tem como valor 100. Então, após a setença de atribuição anterior, m tem o valor 2000. endereço memória ... 1999 2000 100 2001 2002 ... 8 Prof. Lucas Ferrari de Oliveira Ponteiros Operadores para PonteirosOperadores para Ponteiros operador *: Operador unário; Devolve o valor da variável localizada no endereço que o segue (ou seja, este operador sempre interpreta seu operando como um endereço de memória!) 9 Prof. Lucas Ferrari de Oliveira Ponteiros Operadores para PonteirosOperadores para Ponteiros operador *: Exemplo: seguindo o exemplo anterior, se m contem o endereço da variável count, q=*m; coloca o valor de count em q. Agora q tem o valor 100 porque 100 está armazenado na posição 2000, endereço da memória em que está armazenado m. 10 Prof. Lucas Ferrari de Oliveira Ponteiros Operadores para PonteirosOperadores para Ponteiros operador *: Exemplo: seguindo o exemplo anterior, se m contem o endereço da variável count, q=*m; coloca o valor de count em q. Agora q tem o valor 100 porque 100 está armazenado na posição 2000, endereço da memória em que está armazenado m. Pode-se pensar no * como significando “o conteúdo do endereço …”. Assim, a sentença poderia ser lida como “q recebe o conteúdo do endereço m”. Pode-se pensar no * como significando “o conteúdo do endereço …”. Assim, a sentença poderia ser lida como “q recebe o conteúdo do endereço m”. 11 Prof. Lucas Ferrari de Oliveira Ponteiros ObservaçãoObservação Infelizmente, o símbolo de multiplicação e o símbolo de “o conteúdo do endereço …” são iguais, e o símbolo para o AND bit a bit e o símbolo de “o endereço de” também são iguais. Ambos * e & têm precedência maior que todos os operadores aritméticos, exceto o menos unário, que tem mesma precedência. 12 Prof. Lucas Ferrari de Oliveira Ponteiros Declarando PonteirosDeclarando Ponteiros Variáveis que armazenam endereços de memória, os ponteiros (como são chamadas em C), devem ser declaradas colocando-se * em frente ao nome da variável para indicar ao compilador que ela guardará um ponteiro para aquele tipo de variável. 13 Prof. Lucas Ferrari de Oliveira Ponteiros Declarando PonteirosDeclarando Ponteiros Por exemplo, para declarar uma variável ponteiro ch para char, escreve-se: char *ch; Aqui, ch não é um caractere, mas um ponteiro para caractere (há uma grande diferença). 14 Prof. Lucas Ferrari de Oliveira Ponteiros Declarando PonteirosDeclarando Ponteiros Pode-se misturar diretivas de ponteiro e de não- ponteiro na mesma declaração, como por exemplo: int x, *y, count; Declara x e count como sendo do tipo inteiro e y como sendo um ponteiro para o tipo inteiro. 15 Prof. Lucas Ferrari de Oliveira Ponteiros Declarando PonteirosDeclarando Ponteiros E o que faz o programa que segue? #include <stdio.h> int main(void) { int target, source, *m; source = 10; m = &source; target = *m; printf(“%d”, target); } 16 Prof. Lucas Ferrari de Oliveira Ponteiros Expressões com PonteirosExpressões com Ponteiros Em geral, expressões envolvendo ponteiros concordam com as mesmas regras de qualquer outra expressão em C. 17 Prof. Lucas Ferrari de Oliveira Ponteiros Atribuições de PonteirosAtribuições de Ponteiros Como qualquer variável, um ponteiro pode ser usado do lado direito de um comando de atribuição para se passar seu valor para outro ponteiro. #include <stdio.h> void main(void) { int x, *p1, *p2; p1 = &x; p2 = p1; printf(“%p”, p2); //escreve o endereco de x, nao seu valor } 18 Prof. Lucas Ferrari de Oliveira Ponteiros Aritmética de PonteirosAritmética de Ponteiros Existem apenas duas operações aritméticas que podem ser feitas com ponteiros: Adição Subtração Regras da aritmética de ponteiros:Regras da aritmética de ponteiros: Cada vez que um ponteiro é incrementado, ele aponta para a posição de memória do próximo elemento do seu tipo base. Cada vez que um ponteiro é decrementado, ele aponta para a posição de memória do elemento anterior do seu tipo base 19 Prof. Lucas Ferrari de Oliveira Ponteiros Aritmética de PonteirosAritmética de Ponteiros Exemplo: assuma que estamos usando uma máquina na qual um inteiro ocupa 2 bytes. Então … int *p1, x; p1 = &x; p1++; Suponha que x estava armazenada na posição de memória 2000. Então, após p1++, p1 conterá o valor 2002. 20 Prof. Lucas Ferrari de Oliveira Ponteiros Aritmética de PonteirosAritmética de Ponteiros Também é possível somar ponteiros: p1 = p2 + 100; Além de adição e subtração entre um ponteiro e um inteiro, nenhuma outra operação pode ser efetuada com ponteiros. Particularmente, NÃO é permitido:Particularmente, NÃO é permitido: Adicionar ou subtrair o tipo float ou o tipo double a ponteiros; Multiplicar ou dividir ponteiros; Aplicar os operadores de deslocamento ou de mascaramento bit a bit com ponteiros. 21 Prof. Lucas Ferrari de Oliveira Ponteiros Comparação entre PonteirosComparação entre Ponteiros É possível comparar dois ponteiros em uma expressão relacional. Exemplo: if(p<q) printf(“p aponta para um endereço de memoria mais baixo que q\n”); Geralmente, comparações de ponteiros são utilizadas para verificar se dois ou mais ponteiros apontam para um mesmo objeto (uso em estruturas de dados tais como pilhas, filas etc) 22 Prof. Lucas Ferrari de Oliveira Ponteiros Ponteiros e MatrizesPonteiros e Matrizes Há uma estreita relação entre ponteiros e matrizes. De fato, os índices das matrizes são uma maneira mais confortável para se acessar um dado elemento. char nome[80], *p1, ch; p1 = nome; p1 foi inicializado com o endereço do primeiro elemento da matriz nome: ch = nome[4]; ou ch=*(p1+4); copiam o quinto elemento de nome para ch 23 Prof. Lucas Ferrari de Oliveira Ponteiros Ponteiros e MatrizesPonteiros e Matrizes Acessando uma matriz com índices: for( i=0; nome[i] != ‘\0’; i++) putchar(nome[i]); Acessando uma matriz com ponteiro: for( p=nome; *p; p++) putchar(*p); ou p=nome; while(*p) putchar(*p++); 24 Prof. Lucas Ferrari de Oliveira Ponteiros Ponteiros e MatrizesPonteiros e Matrizes Como qualquer outro tipo básico, ponteiros podem ser organizados em matrizes: int *listas[100]; Para se atribuir o endereço de uma variável inteira, chamada var, ao terceiro elemento da matriz de ponteiros, deve-se escrever: listas[2] = &var; Para encontrar o valor de var, escreve-se: *listas[2]; 25 Prof. Lucas Ferrari de Oliveira Ponteiros Indireção MúltiplaIndireção Múltipla Ocorre quando se tem um ponteiro que aponta para outro ponteiro que (finalmente) aponta para o valor. 1. Indireção simples (vista até agora) 2. Indireção múltipla endereço Ponteiro Valor Variável Valor Variável endereço Ponteiro Valor Variável endereço Ponteiro 26 Prof. Lucas Ferrari de Oliveira Ponteiros Indireção MúltiplaIndireção Múltipla Exemplo: #include <stdio.h> void main(void) { int x, *p, **q; x = 10; p = &x; q = &p; printf(“%d”, **q); //imprime o valor de x } 27 Prof. Lucas Ferrari de Oliveira Ponteiros Ponteiro NuloPonteiro Nulo Após um ponteiro ser declarado, mas antes que lhe seja atribuído algum valor, ele contém um valor desconhecido (lixo de memória); Usar um ponteiro cujo valor é desconhecido provavelmente causará uma falha grave de execução; Convenção: um ponteiro que não aponta para um valor válido de endereço da memória recebe o valor nulo (que é zero); Pode-se usar um ponteiro nulo para marcar o final de uma matriz (‘\0’). 28 Prof. Lucas Ferrari de Oliveira Funções com PonteirosFunções com Ponteiros // funcao que procura um nome int search (char *p[], char *name) { int i; for( i=0; p[i]; ++i) if(strcmp(p[i], name)) return i; return -1; // so chega aqui se nao encontrou name } Slide 1 Slide 2 Slide 3 Slide 4 Slide 5 Slide 6 Slide 7 Slide 8 Slide 9 Slide 10 Slide 11 Slide 12 Slide 13 Slide 14 Slide 15 Slide 16 Slide 17 Slide 18 Slide 19 Slide 20 Slide 21 Slide 22 Slide 23 Slide 24 Slide 25 Slide 26 Slide 27 Slide 28