300 likes | 428 Views
Estrutura de Dados. Ponteiros. Professor Mário Dantas. Contribuição: Professor Marcelo Douglas. Introdução ao uso de Ponteiros. Os ints guardam valores inteiros. Os floats guardam valores de ponto flutuante. Os chars guardam caracteres. Ponteiros guardam endereços de memória.
E N D
Estrutura de Dados Ponteiros Professor Mário Dantas Contribuição: Professor Marcelo Douglas
Introdução ao uso de Ponteiros • Os intsguardam valores inteiros. Os floats guardam valores de ponto flutuante. Os chars guardam caracteres. • Ponteiros guardam endereços de memória. Esta operação pode ser entendida pelo compilador como “carregue o inteiro 55 no endereço de memória 248440”. int j; j = 55; 55 ????? ????? ????? ????? 248440 ?????
Introdução ao uso de Ponteiros • Estamos acostumados a trabalhar com o “conteúdo armazenado nos endereços de memória”, no entanto podemos estender os recursos de nossos programas ao aprendermos a trabalhar com os endereçamentos. • Quando você anota o endereço de um colega está criando um ponteiro. O ponteiro é o papel. Paulo Roberto Rua Rio de janeiro, nº 3455
Introdução ao uso de Ponteiros • Qual é o sentido disto? • Quando você anota o endereço de um colega, você vai usar este endereço para achá-lo. • O C funciona assim. Você anota o endereço de algo numa variável ponteiro para depois usar. • Da mesma maneira, uma agenda, onde são guardados endereços de vários amigos, poderia ser vista como sendo uma matriz de ponteiros no C.
Introdução ao uso de Ponteiros • Um ponteiro também tem tipo. No C quando declaramos ponteiros nós informamos ao compilador para que tipo de variável vamos apontá-lo. Um ponteiro int aponta para um inteiro, isto é, guarda o endereço de um inteiro. • Para declarar um ponteiro temos a seguinte forma geral: • É o asterisco (*) que faz o compilador saber que aquela variável não vai guardar um valor mas sim um endereço para aquele tipo especificado. tipo_do_ponteiro = *nome_da_variável
Introdução ao uso de Ponteiros • Exemplos de criação de ponteiros: • O exemplo declara que desejamos criar uma variável ponteiro para armazenar o endereço de um inteiro. • Eles ainda não foram inicializados (como toda variável do C que é apenas declarada). Isto significa que eles apontam para um lugar indefinido. Este lugar pode estar, por exemplo, na porção da memória reservada ao sistema operacional do computador. int *ptr;
Introdução ao uso de Ponteiros • Usar o ponteiro nestas circunstâncias pode levar a um travamento do micro, ou a algo pior. • O ponteiro deve ser inicializado (apontado para algum lugar conhecido) antes de ser usado. Isto é de suma importância! • Se declararmos o ponteiro fora de qualquer função ele é automaticamente inicializado com um valor que garantidamente não aponta para nenhuma posição de memória. Este valor é NULL.
Introdução ao uso de Ponteiros • Para atribuir um valor a um ponteiro recém-criado poderíamos igualá-lo a um valor de memória. • Mas, como saber a posição na memória de uma variável do nosso programa? • Seria muito difícil saber o endereço de cada variável que usamos, mesmo porque estes endereços são determinados pelo compilador na hora da compilação e realocados na execução.
Introdução ao uso de Ponteiros • Para saber o endereço de uma variável basta usar o operador &. Veja o exemplo: • Criamos um inteiro count com o valor 10 e um apontador para um inteiro pt. A expressão &countnos dá o endereço de count, o qual armazenamos em pt. • Vejamos o programa completo: int count=10; int *pt; pt=&count;
Introdução ao uso de Ponteiros • Como nós colocamos um endereço em ptr, ele está agora "liberado" para ser usado. • Podemos, por exemplo, alterar o valor de count usando ptr. • Para tanto vamos usar o operador "inverso" do operador &. • É o operador *. No exemplo acima, uma vez que fizemos ptr=&counta expressão *ptré equivalente ao próprio count. • Isto significa que, se quisermos mudar o valor de count para 12, basta fazer *pt=12.
Introdução ao uso de Ponteiros Fixando Conteúdo Cria uma variável ponteiro que apontará para o endereço de memória do tipo estabelecido. tipo *variavel; Faz com que a variavel do tipo ponteiro aponte para o endereço de memória da variavel n1 e não ao seu conteúdo. variavel = &n1; *variavel é a mesma coisa de n1, portanto alterar *variavel altera n1. *variavel = n2;
Introdução ao uso de Ponteiros • Qual o resultado do programa abaixo?
Introdução ao uso de Ponteiros • O que faz cada linha do programa abaixo?
Aritmética de Ponteiros Estrutura de Dados
Aritmética de Ponteiros • Existem apenas duas operações aritméticas que podem ser usadas com ponteiros: adição e subtração. • Quando incrementamos um ponteiro ele passa a apontar para o próximo valor do mesmo tipo para o qual o ponteiro aponta. • Isto é, se temos um ponteiro para um inteiro e o incrementamos ele passa a apontar para o próximo inteiro.
Aritmética de Ponteiros • Para exemplificar consideremos p1 um ponteiro para um inteiro com o valor atual de 2000. Assuma que os inteiros ocupam 4 bytes de memória. • Após a expressão: • Quanto será o valor de p1? • p1 contém 2004 e não 2001. Cada vez que p1 é incrementado ele aponta para o próximo inteiro. p1++;
Aritmética de Ponteiros • se você incrementa um ponteiro char* ele anda 1 byte na memória e se você incrementa um ponteiro double* ele anda 8 bytes na memória. • Este é mais um motivo pelo qual o compilador precisa saber o tipo de um ponteiro. • O mesmo princípio da adição é aplicado para a subtração.
Aritmética de Ponteiros • Você não está limitado a apenas incrementar e decrementar. Você pode também somar ou subtrair inteiros de ponteiros. • Faz p1 apontar para o décimo segundo elemento do tipo p1 adiante do elemento que ele está atualmente apontando. p1 = p1 + 12; ………… p1 1 2 3 4 11 12 13
Aritmética de Ponteiros • É importante compreender que estamos falando de operações com ponteiros e não de operações com o conteúdo das variáveis para as quais eles apontam. (*ptr)++ Incrementa o conteúdo da variável apontada por ptr. ptr++ Aponta para a próxima posição onde ptr se encontra. *(ptr+15) Acessa o conteúdo do ptr quinze posições adiante.
Aritmética de Ponteiros • Além de adição e subtração entre um ponteiro e um inteiro, nenhuma outra operação aritmética pode ser efetuada com ponteiros. • Você não pode multiplicar ou dividir ponteiros e não pode adicionar ou subtrair o tipo float ou o tipo double a ponteiros. O que não pode ser feito com ponteiros
Aritmética de Ponteiros • Uma outra operação, às vezes útil, é a comparação entre dois ponteiros. Mas que informação recebemos quando comparamos dois ponteiros? • Em primeiro lugar, podemos saber se dois ponteiros são iguais ou diferentes (== e !=). No caso de operações do tipo >, <, >= e <= estamos comparando qual ponteiro aponta para uma posição mais alta na memória. • Então uma comparação entre ponteiros pode nos dizer qual dos dois está "mais adiante" na memória. A comparação entre dois ponteiros se escreve como a comparação entre outras duas variáveis quaisquer.
Exercícios de Fixação • Supondo que p é um ponteiro para um inteiro, explique a diferença entre: p+; (*p)++; *(p++) • O que quer dizer *(p+10)?
Exercícios de Fixação • Qual o valor de y no final do programa? Após descobrir escreva um comentário em cada comando de atribuição explicando o que ele faz.