• Nenhum resultado encontrado

Como funcionam os Ponteiros

N/A
N/A
Protected

Academic year: 2019

Share "Como funcionam os Ponteiros"

Copied!
39
0
0

Texto

(1)

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

(2)

Ponteiro

PLT: 706

(3)

Como funcionam os Ponteiros

• O

int

guardam inteiros.

• O

float

guardam números

de ponto flutuante.

23

45,89

de ponto flutuante.

• O

char

guardam caracteres.

O ponteiro guardam

endereços de memória

.

ABC

(4)

Um Ponteiro é uma variável que contém o endereço de

Não entendi!

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

Podemos ter um ponteiro para qualquer tipo de

(5)

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. Qual é o sentido disto? Quando

um endereço. 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

(6)

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 para aquele tipo especificado. Exemplos:

endereço para aquele tipo especificado. Exemplos:

int ct;

declara um inteiro

int *pt1;

declara um ponteiro para um inteiro

(7)

Inicializando Ponteiros

O ponteiro deve ser inicializado, ou

seja, apontado para algum lugar

conhecido, antes de ser usado.

conhecido, antes de ser usado.

(8)

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:

int contador=20; 20

int contador=20;

Criamos um inteiro “contador” com valor 20.

int *pt;

Declaramos o ponteiro inteiro “pt”

pt=&contador;

Temos agora o endereço da variável

(9)

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 operador "inverso" do

• Vamos usar o operador "inverso" do

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

(10)

Inicializando Ponteiros

Observação importante

:

apesar do símbolo ser o mesmo, o

operador

* (multiplicação)

não é o

operador

* (multiplicação)

não é o

mesmo operador que o

(11)

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

Por favor,

explica ai novamente...

(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

(12)

Exemplo de Ponteiros - 01

#include <stdio.h> int main ()

{ int num,valor;

int *pt;

num=55;

pt=&num; // 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);

(13)

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=&numero; // Pega o endereço de num

pz=&numero; // 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);

(14)

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.

(15)

Qual o resultado de y?

4

0 0

2293476

y x

p

4

4 44

(16)

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 coloca o endereço de bb em zz

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

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

10 0 229346

int cc

ponteiro zz

int bb

(17)

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

• Assim uma cópia dos valores dos argumentos é

Função

Passagem de argumentos

por Valor

• 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

(18)

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

somaDois(valorX,valorY); Isso a gente

somaDois(valorX,valorY);

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 Ponteiso

(19)

• Agora vamos passar como parâmetros da função os ponteiros de variáveis do

Função

Passagem de argumentos através de Ponteiros

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ã???

(20)

int main(){ int valorW; 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);

} Função: Passagem

Passei o endereço da variável

como parâmetro

Mostra outra ai...!

} Função: Passagem

de argumentos através de ponteiros

Recebe um ponteiro

(21)

int main(){

int valorA = 10; int valorB = 200;

troca(&valorA, &valorB); printf("Valor A = %d\n",valorA); printf("Valor B = %d\n",valorB); return(0); } Função Passagem de argumentos através de Ponteiros Passa o endereço

das variáveis como parâmetros

Na função os parâmetros são declarados como ponteiros: p1 e p2

}

O valor do ponteiro p1

O endereço do ponteiro &p1

O valor variável apontada pelo ponteiro *p1

(22)

int main(){

int valorQ; int valorE;

atualiza(&valorQ, &valorE); printf("Valor Q = %d\n",valorQ); printf("Valor E = %d\n",valorE); return(0); } Função Passagem de argumentos através de Ponteiros Passa o endereço

das variáveis como parâmetros

Na função os parâmetros são declarados como ponteiros: pQ e pE

}

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

realizadas pela função “atualiza”.

(23)

Para fazer que

pn

aponte para o mesmo lugar que

pm

int hh=100; int *pm, *pn;

pm = &hh; // Pega o endereco de hh e coloca em pm

Atenção para alguns detalhes

muito importantes... 1

pm = &hh; // Pega o endereco de hh e coloca em pm

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

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

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

100 2293400 2293400

pn

bb pm

100 *pm

(24)

Os ponteiros devem

ser inicializados!!!

Outro detalhe muito

importante... 2

Se não inicializarmos um ponteiro pode fazer com que ele esteja

alocando um espaço de memória utilizado,

main (){

int x int *pt; x =13;

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

}

de memória utilizado, por exemplo, pelo

sistema operacional

Vai dar erro!

(25)

main (){

int x int *pt; x =13;

E como eu resolvo isso de inicializar ponteiro?

Inicializando o ponteiro

com algum endereço!

x =13;

pt = &x;

//inicializei pt com o endereço de x

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

(26)

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 0

pt 2293424 2293400

(27)

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; Endereço do “contador” armazenado em pt

Revisão

Ponteiros

pt=&contador; Endereço do “contador” armazenado em pt

*pt=12. Muda o valor do “contador” para 12.

(28)

Alocação

Estática e

Dinâmica de

Memória

PLT: 706

(29)

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:

29

por exemplo:

(30)

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.

30

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.

(31)

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:

31

biblioteca, é preciso incluir no programa:

(32)

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: Tipo char ocupa 1 byte

32

por exemplo:

char *ponteiro;

ponteiro =

(char*)

malloc

(1);

Aloca 1 byte de memória e

coloca o endereço em um ponteiro

(33)

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.

33

abaixo é o char.

char *ponteiro;

ponteiro = (char*)

malloc

(1);

(34)

Operador

sizeof

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

então utilizamos o operador

sizeof

.

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

int iNumero = 0;

34

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

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

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

}

(35)

Função free

• As

variáveis alocadas estaticamente dentro de

uma função desaparecem quando a execução

da função termina

.

• As variáveis alocadas dinamicamente

• As variáveis alocadas dinamicamente

continuam a existir mesmo depois que a

execução da função termina.

(36)

Operador sizeof

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

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

int main()

{ data *p;

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

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

free(p);

(37)

Operador sizeof

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

{ int *p;

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

if (p == null)

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

37

utilizado no malloc

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

}

*p = 5;

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

free(p);

(38)

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.

(39)

MUITO OBRIGADO!

viniciussouzamg@gmail.com

Referências

Documentos relacionados

Nessa situação temos claramente a relação de tecnovívio apresentado por Dubatti (2012) operando, visto que nessa experiência ambos os atores tra- çam um diálogo que não se dá

a) O polícia disse um palavrão, após ter saído da casa de Adrian. Corrige as falsas.. A mãe também está com gripe. “Quase que não consegui ficar calado quando vi que não

A Procuradoria-Geral de Justiça do Ministerio Publico do Estado de Minas Gerais, por meio do Centro de Estudos e Aperfeiçoamento Funcional (CEAF), no uso das prerrogativas que lhe

O valor da reputação dos pseudônimos é igual a 0,8 devido aos fal- sos positivos do mecanismo auxiliar, que acabam por fazer com que a reputação mesmo dos usuários que enviam

Este trabalho teve por objetivo o estudo da dimensão das doenças crônicas, especificamente o diabetes mellitus, visando à elaboração de um modelo de processo

Our contributions are: a set of guidelines that provide meaning to the different modelling elements of SysML used during the design of systems; the individual formal semantics for

In the second and third measurements, howe- ver, there is a thickening of the lateral cortex in patients from the altitude group (group 1) and consequent thinning of the femoral

Tempo de vida das variáveis estáticas 4 Alocação Dinâmica Ponteiros e Heap Liberação de memória Codificação e endereçamento Erros Comuns Usando ponteiros 5