Como funcionam os Ponteiros

Livre

0
0
39
1 year ago
Preview
Full text

  Disciplina: Estrutura de Dados

  Tema da aula: Ponteiro Função: Passagem de argumentos por Valor Função : Passagem de argumentos através de Ponteiros Alocação Estática de Memória Alocação Dinâmica de Memória: malloc e free

  Ponteiro PLT: 706 Páginas: 255 a 314

  Como funcionam os Ponteiros • O int guardam inteiros.

  23

  • O float guardam números

  45,89 de ponto flutuante. de ponto flutuante.

  • O char guardam caracteres.

  ABC

  • O ponteiro guardam

  8792 endereços de memória .

Não entendi!

  • Um Ponteiro é uma variável

  que contém o endereço de que contém o endereço de memória de outra variável.

  • Podemos ter um ponteiro

  para qualquer tipo de variável.

Como funcionam os Ponteiros

  • Quando você anota o endereço de um colega

  você está criando um ponteiro . O ponteiro é

este seu pedaço de papel. Ele tem anotado

um endereço. um endereço. Qual é o sentido disto? Quando Qual é o sentido disto? Quando você anota o endereço de um colega, depois

você vai usar este endereço para achá-lo. Da

mesma maneira, uma agenda, onde são guardados endereços de vários amigos, poderia ser vista como sendo uma

  

Declarando e Utilizando Ponteiros

  • Para declarar um ponteiro temos a seguinte forma:

  

tipo_do_ponteiro *nome_da_variável;

  • É o asterisco (*) que faz o compilador saber que

  aquela variável não vai guardar um valor mas sim um endereço endereço para aquele tipo especificado. Exemplos: para aquele tipo especificado. Exemplos: declara um inteiro int ct;

declara um ponteiro

int *pt1; para um inteiro ; declara char *temp,*pt2 dois ponteiros para caracteres

Inicializando Ponteiros

  • O ponteiro deve ser inicializado, ou

  seja, apontado para algum lugar conhecido, antes de ser usado. conhecido, antes de ser usado.

  • Para atribuir um valor a um ponteiro recém criado podemos igualar a um valor de memória.

  

Inicializando Ponteiros

  • Podemos então deixar que o compilador faça este trabalho por nós. Para saber o endereço

    de uma variável basta usar o operador &.

    Veja o exemplo:

  20 int contador=20; int contador=20; Criamos um inteiro “contador” com valor 20. int *pt; Declaramos o ponteiro inteiro “pt” pt=&contador; 3454

  

Temos agora o endereço da variável

  

Inicializando Ponteiros

  • Como nós colocamos um endereço em pt, ele está agora "liberado" para ser usado. Podemos, por exemplo, alterar o valor de contador usando pt .
  • Vamos usar o • Vamos usar o operador "inverso" do operador "inverso" do

  operador &. É o operador *. No exemplo, uma vez que fizemos pt=&contador a expressão

  • *pt é equivalente ao próprio contador. Isto

  significa que, se quisermos mudar o valor de contador para 12, basta fazer *pt=12.

Inicializando Ponteiros

  • Observação importante:

  apesar do símbolo ser o mesmo, o operador operador * (multiplicação) * (multiplicação) não é o não é o mesmo operador que o * (referência de ponteiros).

Por favor, explica ai novamente..

  • Para declararmos variáveis do tipo Ponteiro

  int *px, *py; Isso cria duas variáveis do tipo ponteiro (px e py). Essas variáveis podem conter (px e py). Essas variáveis podem conter endereços de variáveis do tipo int.

  • Operadores

  operador direto que retorna o endereço da & variável operando

  • * operador indireto que retorna o conteúdo da variável localizada no endereço .

Exemplo de Ponteiros - 01

  #include <stdio.h> int main () { int num,valor; int *pt; num=55; pt=# // Pega o endereco de num */ valor=*pt; // Valor e igual ao valor armazenado em num printf ("Valor: %d\n",valor);

printf ("Endereco para onde o ponteiro aponta: %p\n",pt);

printf ("Valor da variavel apontada: %d\n",*pt); return(0);

  }

  Exemplo de Ponteiros - 02 Muda o valor de uma variável de forma indireta #include <stdio.h> int main () { int numero,*pz; numero=55; pz=№ pz=№ // Pega o endereço de num // Pega o endereço de num printf ("\nValor inicial: %d\n",numero); // Muda o valor de numero de uma maneira indireta

  • pz=100; printf ("\nValor final: %d\n",numero); return(0); }

  

Adição e Subtração com Ponteiros

Vamos imaginar que p é um ponteiro.

p++ ou p-- ele anda 8 bytes na memória, ou seja, muda o valor do memória, ou seja, muda o valor do endereço de memória. (*p)++ incrementa o conteúdo da variável apontada pelo ponteiro p

Qual o resultado de y?

  y x

  p 2293476

  4

  4

  4

  4

  4

  4

  Por favor, faz uma revisão sobre ponteiros! int bb = 10; int cc = 0;

int *zz; declara um ponteiro do tipo inteiro de nome zz

zz = &bb zz = &bb coloca o endereço de bb em zz coloca o endereço de bb em zz

cc = *zz coloca o valor que esta no endereço zz em cc

int ponteiro

  int bb

  cc zz

  10 229346

  Função Passagem de argumentos por Valor

  • Em C todos os parâmetros de funções são

  passados por valor

  • Assim uma cópia dos valores dos argumentos é • Assim uma cópia dos valores dos argumentos é dada à função que é chamada e ela cria outras

  variáveis temporárias para armazenar esses valores

  • Em C uma função chamada não pode alterar

  

o valor de uma variável da função que a

chamou ; ela só pode alterar a sua cópia temporária int main(){ int valorX; intvalorY; valorX = 5; valorY = 5; printf("\nNo main......................."); printf("\n\tO Valor de a: %d e o seu endereco e: %d\n", valorX, &valorX);

printf("\tO Valor de b: %d e o seu endereco e: %d", valorY, &valorY);

  Isso a gente Isso a gente somaDois(valorX,valorY); somaDois(valorX,valorY); já conhece! printf("No main novamente............."); printf("\n\tO Valor de a: %d e o seu endereco e: %d\n", valorX, &valorX);

printf("\tO Valor de b: %d e o seu endereco e: %d\n", valorY, &valorY);

return(0); }

  Função: Passagem de argumentos através de

Função Passagem de argumentos através de Ponteiros

  • Agora vamos passar como parâmetros da

  função os ponteiros de variáveis do função os ponteiros de variáveis do main, desta forma conseguimos alterar o valor de uma variável do main dentro da função que foi chamada. Hã??? int main(){

  Passei o endereço da variável

  int valorW;

  como parâmetro

  valorW = 5; printf("\nNo main......................."); printf("\n\tO Valor de valorW: %d e o seu endereco e: %d\n", valorW, &valorW); somaTres(&valorW); printf("No main novamente............."); printf("\n\tO Valor de valorW: %d e o seu endereco e: %d\n", valorW, &valorW); return(0);

  Mostra outra ai...! } }

  Função: Passagem Função: Passagem de argumentos Recebe um ponteiro através de ponteiros

Soma os valores que apontam o endereço

  int main(){ Função

  Passa o endereço

  Passagem de int valorA = 10;

  das variáveis como

  argumentos int valorB = 200;

  parâmetros

  através de troca , ); ( &valorA &valorB Ponteiros printf("Valor A = %d\n",valorA);

  Na função os parâmetros

  printf("Valor B = %d\n",valorB);

  são declarados como

  return(0);

  ponteiros: p1 e p2

  } } O valor do ponteiro p1 !!!! Atenção O endereço do ponteiro &p1

  Função

  Passa o endereço

  int main(){ Passagem de

  das variáveis como

  int valorQ; argumentos

  parâmetros

  int valorE ; através de Ponteiros atualiza , ); ( &valorQ &valorE printf("Valor Q = %d\n",valorQ);

  Na função os parâmetros

  printf("Valor E = %d\n",valorE);

  são declarados como

  return(0);

  ponteiros: pQ e pE

  } } !!!! Atenção No main eu criei as variáveis, mas não coloquei dados nas vari[aveis, a atualização das variáveis foram

  

Atenção para alguns detalhes

  1 muito importantes... Para fazer que aponte para o mesmo lugar que pn pm

  int hh=100; int *pm, *pn; pm = &hh; pm = &hh; // Pega o endereco de // Pega o endereco de e coloca em e coloca em

  hh hh pm pm

  pn=pm; // Pega o endereco de e coloca em

  pm pn Para fazer que o conteúdo apontado por tenha o mesmo pn conteúdo da variável apontada por pm

  • *pn=*pm; // Pega o valor apontador por e coloca

  pm pn

  bb

  • *pm *pn pm pn

  Outro detalhe muito

  2 importante...

  Se não inicializarmos

Os ponteiros devem

  um ponteiro pode fazer

  ser inicializados!!! com que ele esteja alocando um espaço utilizado, utilizado, de memória de memória por exemplo, pelo sistema operacional

  main (){ int x

  Vai dar erro!

  int *pt;

  O ponteiro pt não foi inicializado!

  x =13;

  • *pt =x ; //posição de memória de !

  pt é indefinida

E como eu resolvo isso de inicializar ponteiro? Inicializando o ponteiro

  main (){

  com algum endereço!

  int x int *pt; x =13; x =13;

  //inicializei pt com o endereço de x pt = &x;

  • *pt =x ; //posição de memória de !

  pt é definida

  }

  main (){ float salario = 2500; float novoSalario = 0; int *pt;

  //inicialize pt com o //endereço de salario pt = &salario;

  Memória RAM

  Identificação Endereço da Memória Conteúdo

Windows

  0100100 até 0300100 Sistema operacional Windows

  Dev C++ 0300101 até Programa pt = &salario;

  }

  Dev C++ 0300101 até 0400100

  Programa Dec C++ salario 2293400 2500 novoSalario 2293412 pt 2293424 2293400 Revisão Ponteiros

  Revisão Ponteiros O ponteiro deve ser inicializado, antes de ser usado.

  int contador=20; Criamos um inteiro “contador”. int *pt; Declaramos o ponteiro inteiro “pt” pt=&contador; pt=&contador; Endereço do “contador” armazenado em pt Endereço do “contador” armazenado em pt *pt=12. Muda o valor do “contador” para 12. pt++ soma o valor de memória de pt. (*pt)++ incrementa de 1 o “contador”.

  Alocação Estática e Dinâmica de Memória PLT: 706 Páginas: 296 a 297

  

Alocação Estática de Memória

  • Alocação estática de memória ocorre

  antes que o programa comece a ser executado , por exemplo: por exemplo:

  • char nome;
  • int contador;
  • int vetor[10];

  

Alocação Dinâmica de Memória

  • Em determinados sistemas a quantidade de

  

memória que deve ser alocada só se torna

conhecida durante a execução do programa , assim é necessário recorrer ao processo de alocação dinâmica de memória. alocação dinâmica de memória.

  • O processo de alocação retorna um endereço físico de memória para o tipo de variável que se pretende guardar. O endereço é guardado num apontador.
  • O tipo de apontador indica o tipo de dados que são guardados.

  

Alocação Dinâmica de Memória

  • A alocação dinâmica é gerenciada pelas funções malloc e free , que estão na biblioteca stdlib . Para usar esta

    biblioteca, é preciso incluir no programa: biblioteca, é preciso incluir no programa:

    #include < stdlib.h >

Função malloc

  • malloc , abreviatura de memory allocation,

  

aloca um bloco de bytes consecutivos na

memória do computador e devolve o endereço desse bloco em um apontador, por exemplo: por exemplo:

  Tipo char ocupa 1 byte Tipo char ocupa 1 byte char *ponteiro; ponteiro = (char*) malloc (1);

  Aloca 1 byte de memória e coloca o endereço em um ponteiro

Função malloc

  • O retorno de malloc é um ponteiro void*

  

então temos que converter o ponteiro void*

no ponteiro do tipo correto que no exemplo

abaixo é o char. abaixo é o char. char *ponteiro; ponteiro = (char*) malloc (1);

  Conversão do retorno de malloc void* em char *

  Em determinados casos podemos não saber a quantidade de bytes devemos alocar,

Operador então utilizamos o operador . sizeof sizeof

  #include <stdio.h> #include <stdlib.h> int main (void) {

  int iNumero = 0; int iNumero = 0; char cLetra = 'A';

  Número

  struct data {int dia,mes,ano;};

  de Bytes

  printf ("sizeof (int) = %d\n", sizeof(iNumero)); printf ("sizeof (char) = %d\n", sizeof(cLetra)); printf ("sizeof (data) = %d\n", sizeof(data)); return (0);

  }

Função free

  • • As variáveis alocadas estaticamente dentro de

  uma função desaparecem quando a execução da função termina .

  • As • As variáveis alocadas dinamicamente variáveis alocadas dinamicamente

  continuam a existir mesmo depois que a execução da função termina .

  • Para liberar a memória ocupada por essas

  variáveis dinâmicas é preciso recorrer à função free.

  #include <stdio.h> #include <stdlib.h>

  struct data {int dia,mes,ano;};

  int main() { data *p;

  p =(data*) malloc (sizeof(data));

  Operador p.dia=10; sizeof p.mes=3; p.mes=3; utilizado p.ano=2012; no malloc printf("Dia:%d\nMes:%d\nAno:%d\n", p.dia, p.mes, p.ano);

  free(p);

  return 0; }

  “Há memória suficiente disponível para alocar um bloco de memória do tamanho solicitado?“

  #include <stdio.h> #include <stdlib.h> int main() { int *p;

  Operador p = (int*)malloc(sizeof(int)); sizeof if (p == null) utilizado

  { printf("ERRO: Sem memória\n"); no malloc return 1;

  }

  • p = 5; printf("%d\n", *p);

  free(p);

  return 0;

Referências

  • Feofiloff, Paulo. Alocação dinâmica de

  memória; Disponível em: <http://www.ime.usp.br/~pf/algoritmos/aulas/ aloca.html>. Acesso em: 14/04/2014.

  • MIZRAHI, Victorine V.. Treinamento em

  Linguagem C. 2ª ed. São Paulo: Pearson, 2008. (PLT: 706)

  MUITO OBRIGADO! viniciussouzamg@gmail.com sites.google.com/site/viniciussouzamg

Novo documento