• Nenhum resultado encontrado

Ponteiros Slides Introdução à Programação Engenharia de Computação UFPB Ponteiros

N/A
N/A
Protected

Academic year: 2018

Share "Ponteiros Slides Introdução à Programação Engenharia de Computação UFPB Ponteiros"

Copied!
38
0
0

Texto

(1)

PONTEIROS

(2)

Introdução

 Para armazenar dados no computador um programa gerencia:

 Onde a informação esta armazenada

 Que tipo de informação é armazenada

 Que valor é mantido lá

00001100

00110110 Endereços de Memória

3126 (short)

(3)

Introdução

 A declaração de uma variável num programa realiza estes passos necessários para o

armazenamento de dados

short total; // declaração de variável

total = 3126; // atribuição de valor

00001100 00110110

3126 = total

0xCB20 0xCB21 0xCB22 0xCB23 0xCB24 0xCB25 = total 0xCB20 0xCB21 0xCB22 0xCB23 0xCB24 0xCB25 short

(4)

Endereços de Variáveis

 Todo nome de variável esta associado a um endereço na memória

 O operador de endereço & pode ser usado para obter a localização de uma variável

int total; // declaração de variável

total = 3126; // atribuição de valor

printf %d , total ; // valor da variável

(5)

Endereços de Variáveis

#include <stdio.h>

#include <stdlib.h>

int main() {

int copos = 6;

double cafe = 4.5;

printf("Valor de copos = %d , copos);

printf( endereço de copos = %p , &copos);

printf("Valor de cafe = %f , café); printf("Endereço de cafe = %p , &café);

system("pause");

(6)

Ponteiros

 Existe outra estratégia para armazenar dados no computador:

 Alocar memória manualmente

 Guardar o endereço de memória em um ponteiro

 Usar o ponteiro para acessar e modificar os dados

(7)

Ponteiros

 Um ponteiro é um tipo especial que guarda valores que são endereços de memória

 Da mesma forma que uma variável char tem um caractere como valor e um int tem um

número como valor

2.6

0x27FCF8

120

G ch

num ptr mult 0x27FCF8 0x27FCF9 0x27FCFD 0x27FD01

char ch = 'G';

int num = 120;

float mult = 2.6;

char * ptr = (char *) 0x27FCF8;

0x27FD05

(8)

Ponteiros

 A declaração de um ponteiro segue o seguinte padrão:

char * ptr;

O tipo do elemento apontado Nome do ponteiro

(9)

Ponteiros

 Como o ponteiro contém um endereço de memória, diz-se que ele aponta para aquela posição de memória

2.6

0x27FCF8

120

G ch

num ptr mult 0x27FCF8 0x27FCF9 0x27FCFD 0x27FD01 0x27FD05 0x27FD09

char ch = 'G';

int num = 120;

float mult = 2.6;

(10)

Ponteiros

 O nome de um ponteiro

representa uma localização na memória

 O operador de indireção * pode ser usado para obter o valor armazenado na memória

// declaração do ponteiro

char * ptr = (char *) 0x27FCF8;

ptr; // endereço armazenado

*ptr; // valor apontado

2.6

0x27FCF8

120

G ch

(11)

Ponteiros

#include <stdio.h>

#include <stdlib.h>

int main() {

int total = 6; // declara uma variável

int * pt; // declara um ponteiro

pt = &total; // atribui endereço de total

printf("Valor de total = %d" , total); printf("Valor de pt %d = , *pt);

printf("Endereço de total = %p , &total); printf("Endereço de pt = %p , pt);

*pt = *pt + 1; // altera valor

printf("Agora total vale = %d , total);

system("pause");

(12)

Variável

versus

Ponteiro

 Ao usar uma variável:

 O valor é um elemento que possui um nome

 A localização do valor é um elemento derivado (&)

 Ao usar um ponteiro:

 A localização é um elemento que possui um nome

 O valor é um elemento derivado (*)

int * pt = &total; // pt se refere ao endereço

*pt; // *pt se refere ao valor

int total = 6; // total se refere ao valor

(13)

Declaração de Ponteiros

 Por que não se declara um ponteiro da mesma forma que um int, char ou float?

 Não é suficiente dizer que uma variável é um ponteiro, é preciso também especificar para que tipo de dado ele aponta

char ch = 'G';

int num = 120;

float f = 2.1;

char * pc = &ch;

int * pi = &num;

float * pf = &f;

(14)

Declaração de Ponteiros

 Na declaração de um ponteiro o uso de espaços ao redor do (*) é opcional

 Cuidado com declarações múltiplas

int *ptr; // enfatiza que *ptr é um int

int* ptr; // enfatiza que ptr é um ponteiro para int

int * ptr; // estilo neutro

// p1 é um ponteiro para int, p2 é um int

int * p1, p2;

// p1 e p2 são ponteiros para int

(15)

Cuidado com Ponteiros

 Ao declarar um ponteiro o computador não aloca automaticamente memória para

guardar o valor apontado

long * ptr; *ptr = 504;

ptr 0x27FCF8

504

ptr

float val;

float * ptr = &val; *ptr = 504;

(16)

Alocação de Memória

 Ponteiros tem sido usados para guardar endereços de variáveis já existentes

 Variáveis são memórias rotuladas durante o processo de compilação

 Neste caso os ponteiros fornecem apenas uma

segunda forma de acesso as variáveis

 O verdadeiro poder dos ponteiros está em

(17)

Alocação de Memória

 A alocação de memória é feita com o

operador new

int * pn = new int;

Operador new

retorna o endereço da memória alocada Tipo de dado Ponteiro compatível com o

(18)

Alocação de Memória

#include <stdio.h>

#include <stdlib.h>

int main() {

int * pi = new int; // aloca memória para um inteiro

*pi = 1001; // guarda um valor lá

printf("Valor inteiro = %d \n , *pi); printf("Localização = %p \n\n , pi);

double * pd = new double; // aloca memória para um double

*pd = 500.35; // guarda um valor lá

printf("Valor do double = %lf , *pd); printf( Sua localização = %p \n\n , pd);

system("pause"); return 0;

(19)

Liberando Memória

 Toda memória alocada com new deve ser liberada ao final do seu uso

 O operador delete permite retornar a memória não mais usada para uso do sistema, ou de novas alocações

int * ps = new int; // aloca memória com new

... // usa memória

(20)

Liberando Memória

 O operador delete libera a memória mas não destrói o ponteiro

 O mesmo ponteiro pode ser usado para receber outro endereço de memória

int * ps;

ps = new int; // aloca memória com new

*ps = 30; printf( %d , *ps);

delete ps; // libera memória ao final

ps = new int; // aloca nova memória

*ps = 50;

printf( %d ,*ps);

(21)

Liberando Memória

 Um uso de new deve ser sempre balanceado

com um uso de delete

 Caso contrário tem-se um memory leak

int * ps = new int; // aloca memória com new

*ps = 30; printf( %d , *ps);

ps = new int; // memory leak

*ps = 50; printf( %d , *ps);

(22)

Liberando Memória

 Não se pode liberar o mesmo bloco de memória duas vezes

int * ps = new int; // aloca memória com new

*ps = 30;

...

delete ps; // libera memória ao final

(23)

Liberando Memória

 Não se pode usar delete para liberar memória criada com a declaração de variáveis

int val; // declaração de variável

val = 30;

...

(24)

Vetores Dinâmicos

 Um vetor criado por uma declaração de variável é chamado de vetor estático

 É preciso definir previamente o tamanho do vetor em tempo de compilação

 Usando new é possível criar um vetor com tamanho definido durante a execução do programa

(25)

Vetores Dinâmicos

 Para criar um vetor dinâmico com new basta passar o tipo e o número de elementos

 O ponteiro recebe o endereço do primeiro elemento do vetor

int * vet = new int [20];

Operador new

Tipo de dado Ponteiro compatível com o

tipo de dado requisitado

(26)

Vetores Dinâmicos

 Para liberar a memória de um vetor dinâmico

é preciso usar delete com uma notação especial

delete [] vet;

Operador delete Endereço da memória alocada

(27)

Vetores Dinâmicos

 O ponteiro de um vetor dinâmico pode ser usado como se fosse um vetor

5 15

0x27FD09

0x27FD0D

30 0x27FD11

28 0x27FD15

pvet int * pvet = new int [5];

pvet[0] = 15; pvet[1] = 5; pvet[2] = 30; pvet[3] = 28; pvet[4] = 40;

40 0x27FD19 0x27FD1D 0x27FD01

0x27FD05

(28)

Vetores Dinâmicos

#include <stdio.h>

#include <stdlib.h>

int main() {

double * p3 = new double [3]; // memória para três doubles

p3[0] = 0.2; p3[1] = 0.5; p3[2] = 0.7;

printf("p3[1] = %lf \n\n", p3[1]);

p3 = p3 + 1; // incrementa o ponteiro

printf("Agora p3[0] = %lf", p3[0]); printf("Agora p3[1] = %lf , p3[1]); p3 = p3 - 1; // retorna ao inicio

delete [] p3; // libera a memória

system("pause"); return 0;

(29)

Vetores Dinâmicos

 Note que um ponteiro é uma variável e seu conteúdo pode ser modificado através de uma atribuição

p3 = p3 + 1; // incrementa o ponteiro

(30)

Vetores Dinâmicos

 Um ponteiro pode ser usado como um vetor

 Um vetor pode ser usado como um ponteiro

int * pvet = new int [10]; pvet[0] = 15;

pvet[1] = pvet[0] + 5;

int vet[10];

*vet = 15; // vet[0] = 15;

(31)

Vetores Dinâmicos

 Um vetor estático é um ponteiro constante

para o primeiro elemento do vetor

5 15

0x27FD09

0x27FD0D

30 0x27FD11

28 0x27FD15

vet

int vet[5]; vet[0] = 15; vet[1] = 5; vet[2] = 30; *(vet+3) = 28; *(vet+4) = 40;

vet = vet + 1; // inválido

40 0x27FD19 0x27FD1D 0x27FD01

0x27FD05

(32)

Registros Dinâmicos

 O operador new também pode ser usado para criar registros dinâmicos

jogador * pj = new jogador;

Operador new

Tipo de dado Ponteiro compatível com o

tipo de dado requisitado

struct jogador {

(33)

Registros Dinâmicos

 O operador membro (.) não pode ser usado

com um registro dinâmico

 C oferece o operador (->) para acessar membros

de um registro dinâmico

 Usa-se (.) com variáveis tipo registro

 Usa-se (->) com ponteiros para registros

(34)

Registros Dinâmicos

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

struct jogador {

char nome[40]; float salario; unsigned gols; };

int main() {

jogador * pbeb = new jogador; strcpy(pbeb->nome, "Bebeto"); pbeb->salario = 200000;

pbeb->gols = 600;

printf("Contratação para o próximo ano: %s com salario R$ %f. \n , pbeb->nome, pbeb->salario);

delete pbeb;

system("pause"); return 0;

(35)

Registros Dinâmicos

 Atribuição a um registro dinâmico:

jogador * prom = new jogador; strcpy(prom->nome, "Romario"); prom->salario = 300000;

(36)

Vetores Dinâmicos

 O operador new também pode ser usado para criar vetores dinâmicos de registros

jogador * pt = new jogador [22];

Operador new

Tipo de dado Ponteiro compatível com o

tipo de dado requisitado

struct jogador {

char nome[40]; float salario; unsigned gols; };

(37)

Vetores Dinâmicos

 O operador (.) deve ser usado com a notação de vetor

 O operador (->) deve ser usado com a notação de ponteiro

printf( %s , pt->nome); // nome do primeiro jogador

printf( %f , (pt+1)->salario); // salario do segundo jogador

printf( %u , (pt+21)->gols); // gols do ultimo jogador

printf( %s , pt[0].nome); // nome do primeiro jogador

printf( %f , pt[1].salario); // salario do segundo jogador

(38)

Conclusão

 Ponteiros são variáveis que armazenam endereços de memória

 A sua principal função é guardar o endereço de memória alocada dinamicamente com o operador new

 Permite alocar variáveis durante a execução

 Permite criar vetores dinâmicos

Referências

Documentos relacionados

Ao discorrerem sobre o conhecimento pedagógico, como um desdobramen- to do campo geral de significação da Pedagogia, os professores formadores colocaram em movimento, por meio

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

 Na alocação dinâmica, o espaço para as variáveis pode ser alocado dinamicamente durante a.. execução

Como resultado, a memória alocada para esse objeto não pode ser recuperada, levando a uma falha no OutOfMemoryError.. Por exemplo, uma instância de Activity do Android não é mais

producer notify : producted item number 355 Consumer notify : consumed item number 355 consumer is waiting. producer notify : producted item number 876 Consumer notify :

Ausência de mecanismos para restringir acesso (visibilidade) a variáveis e métodos acesso (visibilidade) a variáveis e métodos.

Note como os três ponteiros agora são diferentes: p1 está apontando para um objeto associado a uma variável alocada pelo compilador; p2 está apontando para um objeto

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