• Nenhum resultado encontrado

Ponteiros e Alocação Dinâmica de Memória

N/A
N/A
Protected

Academic year: 2019

Share "Ponteiros e Alocação Dinâmica de Memória"

Copied!
34
0
0

Texto

(1)

Ponteiros

e

Alocação Dinâmica de Memória

Programação de Computadores I

Natália Batista

https://sites.google.com/site/nataliacefetmg/

nataliabatista@decom.cefetmg.br

(2)

1. Memória

A memória RAM de qualquer computador é uma

sequência de bytes.

Cada byte armazena um de 256 possíveis

valores.

Cada objeto na memória ocupa um certo número

de bytes consecutivos. Exemplos:

Um char ocupa 1 byte.

Um int ocupa 4 bytes

Um double ocupa 8 bytes.

(3)

1. Memória

O operador

sizeof (

tipo

)

retorna o tamanho em bytes ocupado

em memória pelo tipo de dado passado como parâmetro.

Exemplo:

sizeof(int)

=> 4 bytes

sizeof(char)

=> 1 byte

sizeof(struct ponto)

=> 8 bytes

Os tamanhos

dependem da

arquitetura da

máquina.

(4)

2. Endereços

Os

bytes

da

memória

são

numerados

sequencialmente e o número de um byte é o seu

endereço

(=

address

).

Cada objeto na memória tem um endereço.

Geralmente o endereço de um objeto é o

endereço do seu primeiro byte.

O endereço é dado pelo operador

&

. Se

i

é uma

variável então:

&

i

é o seu endereço.

(5)

2. Endereços

Por exemplo, depois das declarações

os endereços das variáveis poderiam ser os seguintes:

char c;

int i;

struct {

int x, y;

} ponto;

int v[4];

c 89421

i 89422

ponto 89426

v[0] 89434

v[1] 89438

v[2] 89442

v[3] 89446

(6)

2. Endereços

No exemplo anterior:

&

i vale 89422.

&

v[3] vale 89446.

Outro exemplo: o segundo argumento da função

scanf

é o

endereço da variável onde deve ser depositado o objeto lido da

entrada:

int i;

scanf ("%d",

&

i);

c 89421

i 89422

ponto 89426

v[0] 89434

v[1] 89438

v[2] 89442

v[3] 89446

(7)

3. Ponteiros

Um ponteiro (= apontador =

pointer

) é um tipo

especial de variável que armazena endereços.

Exemplo:

int a;

int b;

int c;

int *ptr;  //declara um ponteiro para um inteiro

       

a = 90;

b = 2;

c = 3;

ptr = &a;

(8)

3. Ponteiros

Há vários tipos de ponteiros:

ponteiros para bytes,

ponteiros para inteiros,

ponteiros para ponteiros para inteiros,

ponteiros para registros, etc.

Para declarar um ponteiro p para um inteiro:

int *p;

Para declarar um ponteiro p para um registro reg:

struct reg *p;

Para declarar um ponteiro r para um ponteiro que apontará um inteiro:

int **r;

(9)

3. Ponteiros

Se um ponteiro p armazena o endereço de uma

variável i, podemos dizer:

“p aponta para i" ou "p é o endereço de i".

Fonte: http://www.inf.pucrs.br/~pinho/PRGSWB/Ponteiros/ponteiros.html

Uma variável do tipo

t*

contém o

endereço de um objeto do tipo

t

.

(10)

3. Ponteiros

Operador de

derreferência

: *

acessa o conteúdo do endereço apontado

operador unário

Por exemplo, se i é uma variável e p vale &i

então dizer "*p" é o mesmo que dizer "i".

p

i

(11)

3. Ponteiros

Exercício: qual é o valor de

a

b

&a

&b

*a

Fonte: slides de aula da Prof.ª Cristina Murta.

(12)

3. Ponteiros

Exercício: suponha que a, b e c são variáveis

inteiras. O que o seguinte trecho de código faz?

int a, b, c;

int *p; // p é um ponteiro para um inteiro

int *q;

p = &a; // o valor de p é o endereço de a

q = &b; // q aponta para b

(13)

3. Ponteiros

Um ponteiro pode ter o valor especial

NULL

que não é endereço de lugar algum.

A macro NULL está definida na biblioteca

stdlib.h.

Seu valor é 0 na maioria dos computadores.

(14)

3. Ponteiros

Impressão de ponteiros:

Em C, pode-se imprimir o valor armazenado no

ponteiro (um endereço), usando-se a função

printf

com o formatador

%p

na string de formato.

Por exemplo:

Fonte: http://www.inf.pucrs.br/~pinho/PRGSWB/Ponteiros/ponteiros.html

#include <stdio.h>

int main(){

int x;

int *ptr;

ptr = &x;

printf("O endereço de X é: %p\n", ptr);

return 0;

(15)

4. Ponteiros em funções

Suponha que precisamos de uma função que troque os

valores de duas variáveis inteiras, digamos i e j.

A função

não produz o efeito desejado, pois recebe apenas cópias dos

valores das variáveis.

A função troca os valores dessas cópias, enquanto as

variáveis "originais" permanecem inalteradas.

(16)

4. Ponteiros em funções

Para obter o efeito desejado, é preciso passar à função os

endereços das variáveis:

(17)

5. Vetores e ponteiros

Existe uma relação intrínseca entre vetores e apontadores.

Exemplo:

int a[10];

define um vetor

a

de tamanho 10, que é alocado em um bloco contíguo de

memória de tamanho suficiente para conter os 10 objetos:

a[0], a[1], a[2], ..., a[9]

O nome do vetor é o endereço do seu primeiro elemento.

int *pa; //apontador para inteiro

pa = a;

pa = &a[0];

(18)

5. Vetores e ponteiros

Fonte: slides de aula da Prof.ª Cristina Murta.

Aritmética de ponteiros: exemplo

int a[10], i;

int *pa;

pa = a;

for(i=0; i<10; i++){

*(pa+i) = i;

}

int x = *pa; // copia a[0] em x

int y = *(pa+1); // copia a[1] em x

pa++

=> aponta para o próximo elemento

pa--

=> aponta para o anterior

(pa+i) - refere-se ao endereço de a[i]

*(pa+i) - refere-se ao valor armazenado em a[i]

(19)

6. Alocação dinâmica de memória

A memória alocada a cada programa durante sua

execução é dividida em quatro áreas:

Instruções

área que armazena o código C compilado e montado

em linguagem de máquina

Memória estática

onde são criadas as variáveis globais e locais estáticas

Pilha

área em que são executadas as funções e criadas as

variáveis locais

Memória dinâmica: Heap

destinada a armazenar dados alocados

dinamicamente

Dados estáticos

Dados estáticos

Dados

dinâmicos

(Heap)

Dados

dinâmicos

(Heap)

Pilha

Pilha

Instruções

Instruções

memória

(20)

6. Alocação dinâmica de memória

Linguagens de programação como C, C++ e Pascal

permitem dois tipos de alocação de memória:

estática e dinâmica.

Na

alocação estática

, o espaço para as variáveis é

reservado no início da execução, não podendo ser

alterado depois. Exemplo:

int a; int b[20];

Na

alocação dinâmica

, o espaço para as variáveis

pode ser alocado dinamicamente durante a

execução do programa.

(21)

6. Alocação dinâmica de memória

A memória alocada dinamicamente é acessada por

meio de

Apontadores

(

ponteiros

).

Essa memória faz parte de uma área de memória

chamada

heap.

Basicamente, o programa aloca e desaloca

porções de memória do

heap

durante a

execução.

(22)

6. Alocação dinâmica de memória

(23)

6. Alocação dinâmica de memória

A alocação dinâmica de memória permite reservar

espaços de memória de tamanho arbitrário durante a

execução do programa e acessá-los através de

apontadores.

A alocação e liberação desses espaços de memória é

feita por funções da biblioteca

stdlib.h

:

malloc() e calloc()

: alocam espaço de

memória.

realloc()

:

realoca um espaço de memória.

free()

: libera espaço de memória.

(24)

6. Alocação dinâmica de memória

Exemplos:

Alocação de um inteiro.

Alocação de um vetor com 100 caracteres.

Fonte: slides de aula da Prof.ª Cristina Murta..

int *ptr;

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

char *ptr;

(25)

6. Alocação dinâmica de memória

Alocação dinâmica de

matriz

: são implementadas como

vetores de vetores.

Uma matriz com m linhas e n colunas é um vetor cujos m

elementos são vetores de n elementos.

O elemento de M que está no cruzamento da linha i com

a coluna j é denotado por M[i][j].

int **M;

M = (int **) malloc (m * sizeof (int *));

for (int i = 0; i < m; ++i)

(26)

6. Alocação dinâmica de memória

Teste de Alocação:

memória não é infinita!

Para verificar se foi possível alcar a memória solicitada,

pode-se testar o valor do ponteiro usado para armazenar a

área alocada.

Se o valor deste ponteiro for NULL, não foi possível alocar

a memória.

Fonte: http://www.inf.pucrs.br/~pinho/PRGSWB/Ponteiros/ponteiros.html

int *ptr;

ptr = (int*) malloc(sizeof(int)*10);

if (ptr == NULL){

(27)

6. Alocação dinâmica de memória

Liberação de memória:

Todo o espaço alocado ao programa deve ser

retornado ao sistema operacional quando não for

mais necessário ao programa.

Função free(ptr);

Libera o uso de um bloco de memória, permitindo que

este espaço seja reaproveitado

(28)

6. Alocação dinâmica de memória

Exemplo:

#include <stdio.h>

#include <stdlib.h>

int main() {

int *notas, numero, i;

printf("Entre com o número total de alunos: \n");

scanf("%d", &numero);

notas = (int *)

malloc

(numero * sizeof(int));

for (i = 0; i < numero; i++) {

printf("Digite a nota do aluno %d: ", i+1);

scanf("%d", notas+i);

printf("A nota do aluno %d é %d.\n" , i+1, notas[i]);

}

free

(notas);

}

(29)

6. Alocação dinâmica de memória

Mais um exemplo:

Fonte: slides de aula da Prof. David Menotti.

int *a, b;

b = 10;

a

b

Heap

Alocação

Estática

(30)

6. Alocação dinâmica de memória

Fonte: slides de aula da Prof. David Menotti.

int *a, b;

b = 10;

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

*a = 20;

a

20

b

Heap

Alocação

Estática

(31)

6. Alocação dinâmica de memória

Qual é o valor de b no final?

Fonte: adaptado dos slides de aula da Prof.ª Jussara Almeida..

int *a, b, *c;

b = 10;

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

*a = 20;

c = a;

free(a);

a = &b;

*a = 30;

a

20

b

Heap

Alocação

Estática

30

X

c

Memória foi desalocada.

O endereço contido no

(32)

7. Resumo: notação em C

Fonte: slides de aula da Prof.ª Jussara Almeida..

Definição de p como um apontador para uma variável do tipo T

T *p;

Alocação de memória para uma variável apontada por p

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

Desalocação/Liberação de memória

free(p);

Conteudo da variável apontada por p

*p;

Valor nulo para um apontador

NULL;

Endereço de uma variável a

(33)

8. Erros comuns

Esquecer de alocar memória e tentar acessar o

conteúdo da variável.

Copiar o valor do apontador ao invés do valor da

variável apontada.

Esquecer de desalocar memória.

Ela é desalocada ao fim do programa ou procedimento

função onde a variável está declarada, mas pode ser

um problema em loops.

Tentar acessar o conteúdo da variável depois de

desalocá-la.

(34)

9. Atividades sugeridas

Leitura e exercícios do livro-texto (Damas):

Referências

Documentos relacionados

• função malloc retorna o endereço do espaço alocado, que é então convertido para o tipo ponteiro da estrutura. struct

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

mais longos, localizar e relacionar mais de uma mais longos, localizar e relacionar mais de uma informação, comparar vários textos, identificar informação, comparar vários

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

b) Para a realização desta política, o FUNDO investirá, no mínimo, 2/3 do seu valor líquido global em unidades de participação de outros fundos de investimento, incluindo

Faça um programa que leia um valor n e crie dinamicamente um vetor de n elementos e passe esse vetor para uma função que vai ler os elementos desse vetor.. Depois, no

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

algarismo “1” (um) seguido pela coluna composta pelo último algarismo do 2º ao 5º prêmio da extração da Loteria Federal do Brasil, lidos verticalmente de cima para baixo, caso