• Nenhum resultado encontrado

eco02-12-ponteiroAlocacaoDinamica

N/A
N/A
Protected

Academic year: 2021

Share "eco02-12-ponteiroAlocacaoDinamica"

Copied!
40
0
0

Texto

(1)

Alocação Dinâmica

Profa.Dra.Thatyana de Faria Piola Seraphim Universidade Federal de Itajubá

(2)

de memória.

I Nestes endereços da memória é possível colocar valores e em

seguida utilizá-los.

I Os tipos de valores colocados nos endereços de memória são

denidos na declaração de um ponteiro.

I É esse tipo que indica ao compilador a quantidade de memória

necessária para armazenar os valores.

I Uma variável do tipo ponteiro aponta para uma variável de

um determinado tipo (char, int, oat, double, . . .).

I É necessário na declaração de um ponteiro, especicar para

qual tipo de variável ele irá apontar.

I Os ponteiros são declarados com um * antes do nome da

variável. Sintaxe

(3)

int *aux; float *temp; char *pont;

I aux, temp e pont são

variáveis que armazenam endereços de memória e não valores do tipo int, oat, char.

I * é usado quando deseja-se

acessar o valor que está na posição de memória e não ao endereço da memória.

(4)
(5)

Operador & e Operador *

I O operador & e o operador * são utilizados quando se

trabalha com ponteiros. Operador &

I Obtém sempre o endereço de uma variável (endereço de). I Como os ponteiros também são variáveis eles também ocupam

memória.

I Pode-se obter o endereço do ponteiro e ter ponteiros para

ponteiros (múltiplos *). Operador *

I O operador * faz o contrário do operador &.

I Dado um ponteiro, o operador * acessa o conteúdo apontado

(6)

1 #include<stdio.h>

2 int main(int argc, char *argv[]){ 3 int x=10;

4 int *p1=&x; //ponteiro para um inteiro 5 6 printf("x = %d\n\n", x); 7 *p1=20; //ou p1[0]=20; 8 9 printf("p1 = %u\n", p1); 10 printf("x = %d\n", x); 11 printf("*p1 = %d\n", *p1); 12 printf("p1[0] = %d\n\n", p1[0]); 13 return 0; 14 } //end main

(7)

Operador & e Operador *

Exemplo 02 - Ponteiro de Ponteiro que referencia um inteiro

1 int main(int argc, char *argv[]){ 2 int x=10;

3 int *p1=&x; //ponteiro para um inteiro

4 int **p2=&p1; //ponteiro de ponteiro para um inteiro 5 6 printf("x = %d\n\n", x); 7 **p2=30; //ou p2[0][0]=30; 8 9 printf("p2 = %u\n", p2); 10 printf("x = %d\n", x); 11 printf("**p2 = %d\n", **p2); 12 printf("p2[0][0] = %d\n\n", p2[0][0]); 13 return 0; 14 } //end main

(8)

Exercício 01 - Ponteiro de ponteiro de ponteiro que referencia um inteiro

Faça um programa:

1. Declare uma variável x do tipo inteiro e atribua o valor 10.

2. Declare uma variável p3 que seja do tipo ponteiro de ponteiro de ponteiro para um inteiro.

3. A variável p3 deve referenciar um ponteiro, que referencia um outro ponteiro, que referencia a variável inteira x.

4. Modique o valor da variável inteira x para 40 a partir de p3.

(9)

Operador & e Operador *

Resposta do Exercício 01

1 int main(int argc, char *argv[]){ 2 int x=10;

3 int *p1=&x; //ponteiro para um inteiro

4 int **p2=&p1; //ponteiro de ponteiro para um inteiro

5 int ***p3=&p2; //ponteiro de ponteiro de ponteiro para um inteiro 6 7 printf("x = %d\n\n", x); 8 ***p3=40; //ou p3[0][0][0]=40; 9 10 printf("p3 = %u\n", p3); 11 printf("x = %d\n", x); 12 printf("***p3 = %d\n", ***p3); 13 printf("p3[0][0][0] = %d\n", p3[0][0][0]); 14 return 0; 15 }//end main

(10)

I Os ponteiros são necessários na implementação da técnica de

alocação dinâmica.

I Alocação Dinâmica: é a técnica para a alocação e

desalocação de espaço de memória, através de funções pré-denidas pela linguagem C.

I O controle de alocar e desalocar espaço na memória é de

responsabilidade do programador.

I A alocação estática libera automaticamente o espaço alocado

em memória quando o programa sai do escopo (da chave), onde a variável foi declarada.

I A linguagem C fornece funções denidas na biblioteca

<stdlib.h> para alocar e desalocar memória: malloc(), sizeof() e free().

(11)

malloc()

I É responsável por procurar um local livre na memória. I Aloca um bloco de memória com um tamanho de bytes. I Retorna um ponteiro para o bloco alocado.

I O ponteiro deve sempre ser convertido (typecast) para o tipo

de ponteiro usado.

Sintaxe: void *malloc(size_t size); Exemplo:

(12)

sizeof(tipo)

I Devolve o número de bytes necessários para representar os

valores de um tipo de dado. Sintaxe 1: sizeof(tipo);

Sintaxe 2: sizeof(nomeVariavel);

int *idade=(int *) malloc(sizeof(int)); double sal=1234.5;

(13)

free()

I Desaloca a memória que foi alocada com o malloc, cujo

endereço se encontra em um ponteiro.

I Se perder o endereço (ponteiro) para onde a memória foi

alocada (pelo malloc), o espaço cará perdido (sem utilização) até que o programa termine.

I Quando o programa estiver usando toda memória RAM, será

iniciado o uso da memória virtual (swap).

I A memória virtual (swap) utiliza o disco para simular memória

RAM, deixando o programa mais lento. Sintaxe free()

void free(void *ptr); Exemplo

(14)

Exemplo

1 int main(int argc, char *argv[]){

2 int i;

3 char *buffer;

4 for(i=0; i<(100*1024); i++){

5 buffer=(char *)malloc(1024*sizeof(char)); 6 }//end for

7 free(buffer);

8 system("sleep 10");

9 return 0;

(15)

Vetores

Alocação estática de um vetor int v[10];

Alocação dinâmica de um vetor

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

I Ambas alocações são iguais, ou seja, vai ser alocado na

memória 10 posições para v.

I Diferença: na alocação dinâmica é necessário desalocar (free)

(16)

1 int main(int argc, char *argv[]){

2 int i;

3 int *v1; //aloca um vetor de dimensão 10 4 srand(time(NULL));

5

6 //alocacao de um vetor de dimensao 10 7 v1=(int *) malloc(10 * sizeof(int)); 8

9 //atribuição e impressao 10 for(i=0; i<10; i++){ 11 v1[i]=rand()%100;

12 printf("[%d=%d] ", i, v1[i]); 13 }//end for

14 printf("\n"); 15

(17)

Matrizes

Alocação estática da matriz int v[3][4];

Alocação dinâmica de um vetor int i;

int **v=(int **) malloc(3*sizeof(int*)); for(i=0; i<3; i++)

(18)

1 int main(int argc, char *argv[]){

2 //declara uma matriz de dimensao 10x20 3 int **m2;

4 int i, j;

5 //alocacao da matriz 10x20

6 m2=(int**)malloc(10*sizeof(int*)); 7 for(i=0; i<10; i++){

8 m2[i]=(int*)malloc(20*sizeof(int)); 9 }//end for

10 //atribuicao e impressao 11 for(i=0; i<10; i++){ 12 for(j=0; j<20; j++){ 13 m2[i][j]=rand()%100;

(19)

Matrizes  Exemplo

Alocação dinâmica da matriz  Cont.

15 }//end for j 16 printf("\n"); 17 }//end for i 18 printf("\n"); 19 20 //desalocacao da matriz 10x20 21 for(i=0; i<10; i++){

22 free(m2[i]); 23 }//end for 24 free(m2); 25 return 0; 26 } //end main

(20)

Exercício

1. Faça um programa que declare uma matriz tridimensional de inteiros de dimensão 10 × 20 × 30 chamada m3.

2. A matriz m3 deve ser alocada dinamicamente na memória.

3. Deve-se atribuir e imprimir valores à matriz m3.

4. A matriz m3 deve ser desalocada antes que o programa termine.

(21)

Exercício  Resposta

Alocação dinâmica da matriz

1 #include<stdio.h>

2 int main(int argc, char *argv[]){ 3 int i, j, k;

4 int ***m3; //declaracao da matriz tridimensional 5

6 //alocacao da matriz de dimensao 10x20x30 7 m3=(int***) malloc(10 * sizeof(int **)); 8 for(i=0; i<10; i++){

9 m3[i]=(int**) malloc(20 * sizeof(int *)); 10 for(j=0; j<20; j++){

11 m3[i][j]=(int*) malloc(30 * sizeof(int)); 12 }//end for j

(22)

Alocação dinâmica da matriz  Cont.

14 //atribuicao e impressao da matriz de dimensao 10x20x30 15 for(i=0; i<10; i++){

16 for(j=0; j<20; j++){ 17 for(k=0; k<30; k++){ 18 m3[i][j][k]=rand()%100; 19 printf("[%d,%d,%d=%d] ", i, j, k, m3[i][j][k]); 20 }//end for k 21 printf("\n\n"); 22 }//end for j 23 printf("\n"); 24 }//end for i 25 printf("\n");

(23)

Exercício  Resposta

Alocação dinâmica da matriz  Cont.

26 //desalocacao da matriz de dimensao 10x20x30 27 for(i=0; i<10; i++){

28 for(j=0;j<20;j++){ 29 free(m3[i][j]); 30 }//end for j 31 free(m3[i]); 32 }//end for i 33 free(m3); 34 return 0; 35 }//end main

(24)

I O ponteiro de void é um tipo especial de ponteiro. I Ele representa a ausência de um tipo de dado.

I Com o uso do ponteiro para void não é possível acessar

diretamente o valor referenciado.

I É necessário que seja feito uma conversão de tipo de dado.

Sintaxe

(25)

Ponteiro para void  Exemplo

Exemplo

1 #include<stdio.h>

2 int main(int argc, char *argv[]){

3 int i;

4 void *aluno = malloc(10*sizeof(byte)); 5 char *nome = (char *) aluno;

6 int *matricula = (int *) aluno; 7 *matricula = 1234;

8 printf("matricula = %d\n", *matricula); 9 for(i=0; i<10; i++){

10 printf("[%d]", ((char*)aluno)[i]); 11 }//end for i

(26)

Exemplo  Cont.

12 strcpy(nome, "Joao");

13 printf("nome = %s\n", nome); 14 for(i=0; i<10; i++){

15 printf("[%d]", ((char*)aluno)[i]); 16 }//end for i

17 free(aluno); 18 return 0; 19 }//end main

(27)

Ponteiro Nulo

I O ponteiro nulo (NULL) é um valor especial que indica que

um ponteiro de qualquer tipo não está apontando para qualquer referência válida ou endereço de memória.

I Este valor é o resultado de typecasting do valor inteiro zero

para qualquer tipo de ponteiro.

I A diferença de ponteiro nulo e ponteiro para void.

I Ponteiro nulo: representa um valor nulo em um ponteiro de

qualquer tipo, ou seja, não foi atribuído nenhum endereço de memória para a variável.

I Ponteiro para void: é um ponteiro para uma região de

memória sem tipo. Sintaxe

char *buffer=NULL; int *idades=NULL; void *limbo=NULL;

(28)

1 #include<stdio.h>

2 typedef unsigned char byte; 3 int main(int argc, char *argv[]){

4 int i;

5 byte *buffer=NULL;

6 ...

7 if(buffer == NULL){

8 buffer=(byte*) malloc(10*sizeof(byte)); 9 }//end if

10 for(i=0; i<10; i++){ 11 buffer[i]='a' + i;

12 printf("[%c]", buffer[i]); 13 }//end for i

(29)

Ponteiro Nulo

Exemplo - NULL  Cont.

15 if(buffer != NULL){ 16 free(buffer); 17 }//end if 18 return 0; 19 }//end main

(30)

da estrutura podem ser acessados através do operador ponto (.).

I O operador ponto (.) conecta o nome de uma variável

estrutura a um membro da estrutura. Sintaxe para acesso

nomeVariavel.nomeMembro = dados; Exemplo da Estrutura e Acesso

1 typedef struct{ 2 char nome[20]; 3 int idade; 4 }t_aluno; 5 t_aluno a1; 6 strcpy(a1.nome, "Joao");

(31)

Acesso aos Dados Dinâmicos

I Quando a variável do tipo estrutura é um ponteiro, os dados

são acessados usando o operador ponteiro >. Sintaxe para acesso

nomeVariavel>nomeMembro = dados; Exemplo da Estrutura e Acesso

1 typedef struct{ 2 char nome[20]; 3 int idade; 4 }t_aluno;

5 t_aluno *a1 = (t_aluno *) malloc(sizeof(t_aluno)); 6 strcpy(a1->nome, "Joao");

(32)

e seta (>) 1 #include<stdio.h> 2 typedef struct{ 3 char nome[20]; 4 int temp; 5 double preco; 6 }t_seriesTV;

7 int main(int argc, char *argv[]){ 8 t_seriesTV s1; //alocacao estatica 9 //alocacao dinamica

10 t_seriesTV *s2=(t_seriesTV *) malloc(sizeof(t_seriesTV)); 11 strcpy(s1.nome,"Lost");

12 s1.temp=5;

(33)

Estrutura

Exemplo - Acesso membro de estrutura com ponto (.) e seta (>)  Cont.

14 printf("Nome=%s Temporada=%d Preco=%.2f\n",

15 s1.nome, s1.temp, s1.preco);

16 strcpy(s2->nome,"Big Bang Theory"); 17 s2->temp=3;

18 s2->preco=98.76;

19 printf("Nome=%s Temporada=%d Preco=%.2f\n", 20 s2->nome, s2->temp, s2->preco); 21 free(s2);

22 return 0; 23 }//end main

(34)

I Existem duas operações aritméticas que podem ser usadas

com ponteiros:

I Adição (incremento). I Subtração (decremento).

I Quando um ponteiro é incrementado ele passa a apontar para

o próximo valor do mesmo tipo para o qual o ponteiro aponta.

I Se um ponteiro para inteiro for incrementado, esse ponteiro

passa a apontar para o próximo inteiro.

I Isso justica a necessidade do compilador conhecer o tipo de

um ponteiro.

I Se um ponteiro para char * é incrementado, ele anda 1 byte

na memória.

I Se um ponteiro para double * é incrementado, ele anda 8

(35)

Aritmética de Ponteiro

(36)

Exemplo - Aritmética de ponteiro

1 typedef unsigned char byte; 2 int main(int argc, char* argv[]){

3 int i,j;

4 byte *buffer = (byte*) malloc(60 * sizeof(byte)); 5 int *idade = (int *) buffer;

6 double *sal = (double *) buffer + sizeof(int); 7 char *nome = (char *) buffer + sizeof(int) +

8 sizeof(double);

9 *idade=18; //ou idade[0]=18; 10 *sal=510.0; //ou sal[0]=510.0; 11 strcpy(nome,"Joao");

12 printf("Nome = %s Idade = %d Sal = %f\n",

13 nome, *idade, *sal);

14 printf("Nome = %s Idade = %d Sal = %f\n", 15 nome, idade[0], sal[0]);

(37)

Aritmética de Ponteiro Cont. . .

16 //impressao de buffer

17 for(i=0; i<60; i++){

18 printf("[%3d]", buffer[i]); 19 if(((i+1)%10)==0){

20 printf("\n");

21 for(j=i-9; j<=i; j++){ 22 printf(" %3d ", j); 23 }//end for 24 printf("\n"); 25 }//end if 26 }//end for 27 printf("\n"); 28 free(buffer); 29 return 0; 30 }//end main

(38)
(39)

Aritmética de Ponteiro

Exemplo - Aritmética de ponteiro

1 typedef unsigned char byte; 2 int main(int argc, char* argv[]){

3 int i,j;

4 byte *buffer=(byte*) malloc(60 * sizeof(byte)); 5 int *idade1=(int *) buffer;

6 int *idade2=(int *) buffer + sizeof(int); //idade2=idade1+1; 7 char *nome=(char *) buffer + (2*sizeof(int)); //ou

8 //nome=(char*)idade1+2;

9 double *sal1=(double *) buffer + (2*sizeof(int)) + 8; 10 double *sal2=(double *) buffer + (2*sizeof(int)) + 8 +

11 sizeof(double);

12 *idade1=18; //ou idade1[0]=18;

13 *idade2=25; //ou idade2[0]=25; ou idade1[1]=25; 14 *sal1=123.4; //ou sal1[0]=123.4;

15 *sal2=666.66; //ou sal2[0]=666.66; ou sal1[1]=666.66; 16 strcpy(nome,"Itajuba"); //ou strcpy(nome[0],"Itajuba");

(40)

17 printf("Nome=%s Idade1=%d Idade2=%d Sal1=%f Sal2=%f\n", 18 nome, *idade1, *idade2, *sal1, *sal2);

19 printf("Nome=%s Idade1=%d Idade2=%d Sal1=%f Sal2=%f\n", 20 nome, idade1[0], idade2[0], sal1[0], sal2[0]); 21 for(i=0; i<60; i++){ //impressao de buffer

22 printf("[%3d]", buffer[i]); 23 if(((i+1)%10)==0){

24 printf("\n");

25 for(j=i-9; j<=i; j++){ 26 printf(" %3d ", j); 27 }//end for 28 printf("\n"); 29 }//end if 30 }//end for 31 free(buffer); return 0;

Referências

Documentos relacionados

A grande diferença é que um ponteiro deve ser inicializado para uma posição de memória de outra variável (que também deve estar dentro do programa). O tipo da

OBSERVAÇÃO: Em qualquer modo de acerto, se nenhum botão de pressão for accionado durante dois minutos, todas as alterações serão guardadas e o acerto regressará automaticamente

Em outros termos, a perspectiva liberal nada mais pode dizer dos fenômenos nazifascistas além de que sejam governos de poder monopolizado em geral, sob pena de romper com

• Structs são coleções de dados heterogêneos agrupados em um mesmo elemento de dados. • Ex: armazenar as coordenadas (x,y) de um

O presente relatório pretende apresentar a entidade acolhedora e descrever todas as atividades realizadas pela estagiária, durante o seu período de Estágio Curricular,

fato dos bens que compõem este estoque serem indivisíveis e (c) a propriedade privada no que diz respeito às modalidades de acesso à rede, quando essas modalidades geram

autoria de pensamento, compreendendo o(a) aprendente em movimento, em busca de significados e sentidos para as suas práticas. Para entender melhor os processos de

O Produto 5 seguirá um modelo a ser disponibilizado pela Comissão de Seleção e consistirá na síntese dos Produtos 1 a 4, levando-se em consideração o escopo