Buscar

ED_Aula_004 - CCT0637

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 38 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 38 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 38 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

2019.2
ESTUTURAS DE DADOS
CCT0637
Aula 4
PROFESSOR: EDIBERTO MARIANO
1
2019.2
CONTEÚDOS
2
· Alocação Dinâmica de Memória (parte I)
· Fundamentos
· Aplicação em C++: Ponteiros
· Operador de endereço (&)
. Operador de indireção (*)
. Operador seta (->)
2019.2 3
Na alocação dinâmica o espaço de memória, que as variáveis irão
utilizar durante a execução do programa, é definido enquanto o
programa está em execução. Ou seja, quando não se sabe ao certo
quanto de memória será necessário para o armazenamento das
informações, podendo ser determinadas, sob demanda, em tempo de
execução conforme a necessidade do programa.
Alocação Dinâmica de Memória
No padrão C ANSI existem quatro funções para alocação dinâmica 
de memória:
1. malloc() 2. calloc() 3. realloc() 4. free() Todas elas pertencem a 
biblioteca <stdlib.h>. 
int *vetor; vetor = malloc(100); 
2019.2 4
O espaço necessário para a representação dos dados pode ser
alocado à medida que se torne necessário, através da alocação
dinâmica.
Alocação Dinâmica de Memória
Uma estrutura armazenada através de encadeamento apresenta seus
nodos alocados em posições aleatórias na memória, e não lado a
lado.
Dessa forma, existem várias vantagens no uso de representar os dados
por encadeamento.
Compartilhamento de memória
Maleabilidade
Facilidade para inserção
Remoção de componentes
int *p = new int;
As estruturas dinâmicas são assim chamadas, pois podem fazer
alocação de memória em tempo de execução e terem seus tamanhos
alterados de acordo com a demanda.
2019.2 5
Alocação Dinâmica de Memória
Alocação dinâmica de 80 bytes na memória
Assumindo que um valor do tipo inteiro ocupa 4 bytes na memória.
int *p;
p = (int *)malloc(20*sizeof(int));
2019.2 6
Alocação Stática de Memória
Na alocação estática o espaço de memória, que as variáveis irão utilizar 
durante a execução do programa, é definido no processo de 
compilação.
Exemplos
Não sendo possível alterar o tamanho desse espaço durante a execução 
do programa.
char a; Espaço reservado para um valor do tipo char. O char ocupa 1 
byte na memória.
double matriz[3][3]; Espaço reservado para nove(3x3) valores do tipo 
double. O double ocupa 8 bytes na memória, portanto 3x3x8=72 bytes.
int vetor[10]; Espaço reservado para dez valores do tipo int. O int ocupa 
4 bytes na memória, portanto 4x10=40 bytes.
2019.2 7
A utilização de ponteiros em linguagem C é uma das características
que tornam a linguagem tão flexível e poderosa.
Ponteiros ou apontadores, são variáveis que armazenam o endereço
de memória de outras variáveis.
Dizemos que um ponteiro “aponta” para uma varíável quando contém
o endereço da mesma.
Os ponteiros podem apontar para qualquer tipo de variável. Portanto
temos ponteiros para int, float, double, etc.
PONTEIROS
2019.2 8
· Ponteiros são fundamentais para a programação bem sucedida em
C++:
- Passagem de parâmetros por referência;
- Alocação dinâmica de memória;
- Aumentar a eficiência de certar rotinas.
· Essencialmente, um ponteiro nada mais é do que uma variável que
ao invés de conter um valor, contém um endereço de memória.
· O conceito de utilizar espaço em memória não é em absoluto novo.
De fato, linguagens de máquina utilizam tal conceito todo o tempo.
Definições
2019.2 9
Ponteiros são muito úteis quando uma variável tem que ser acessada
em diferentes partes de um programa.
Neste caso, o código pode ter vários ponteiros espalhados por
diversas partes do programa, “apontando” para a variável que contém
o dado desejado.
Caso este dado seja alterado, não há problema algum, pois todas as
partes do programa tem um ponteiro que aponta para o endereço
onde reside o dado atualizado.
Por que usar ponteiros?
2019.2 10
Manipular elementos de matrizes e vetores.
Razões para se usar ponteiros
Receber argumentos em funções que necessitem modificar o
argumento original.
Criar estruturas de dados complexas, como listas encadeadas e
árvores binárias, onde um item deve conter referências à outro.
Passar strings (vetor de caracteres) de uma função para outra.
2019.2 11
- Alocação dinâmica de memória
- Manipulação de arrays.
- Para retornar mais de um valor em uma função.
- Referência para listas, pilhas, árvores e grafos.
Sintaxe de declaração de ponteiro
tipo *nome_ponteiro; ou <tipo> *<nome_variavel>;
Onde temos:
tipo : é o tipo de dado da variável cujo endereço o ponteiro armazena.
*nome_ponteiro : O nome da variável ponteiro.
O asterisco * neste tipo de declaração determina que a variável será 
um ponteiro.
Situações onde ponteiros são úteis
2019.2 12
Declaração de um ponteiro:
int *ptr;
Declaração de vários Ponteiros
Exemplo da declaração de diversos ponteiros:
int *iptr;
float *fptr;
char *cptr;
Como um ponteiro armazena um endereço de memória e não um valor específico, no entanto, 
muito comumente, deseja-se acessar o valor armazenado pela variável apontada por um ponteiro.
Desta forma, o tipo do ponteiro serve para instruir o compilador na maneira pela qual o dado 
pontado será acessado. Essencialmente, o tipo de dados e a codificação do dado (como os bits serão 
interpretados, necessário por exemplo para tipos com base na notação de ponto flutuante).
Declaração de Ponteiros
2019.2 13
Ponteiros são inicializados ao definirmos um endereço para o qual eles devem apontar.
Ponteiros não inicializados são também chamados de "ponteiros Selvagens".
A não inicialização de ponteiros é um dos principais fatores para erros em tempo de
execução em programas escritos na linguagem C++. Tais erros são difíceis de identificar e
corrigir, porque o tempo decorrido entre o acesso ilegal à memória de um ponteiro e a
efetiva ocorrência do erro é imprevisível.
Uma maneira de garantir que um ponteiro declarado não apontará para um lugar
qualquer da memória é atribuir o valor NULL para o mesmo.
int *iptr = null; 
Inicialização de Ponteiros
2019.2 14
"*" conteúdo / indireção: aplicado a um variável tipo ponteiro, 
retorna o conteúdo do endereço apontado pelo ponteiro;
"&" endereço: aplicado a uma variável, retorna seu endereço de 
memória.
Exemplo da utilização de ambos os operadores unários:
int count;
int *iptr;
iptr = &count;
cout << *iptr;
Operadores de Ponteiros
2019.2 15
#include <stdio.h> //PARA USO DO PRINTF
#include<iostream>
using namespace std;
#include <conio.h>
int main(void) {
int num = 40; //num é a variável que será apontada pelo ponteiro
int *ptr; //declaração de variável ponteiro
ptr = &num; //atribuindo o endereço da variável num ao ponteiro
cout<<"CRIANDO E USANDO PONTEIRO\n\n";
cout<<"PROF: EDIBERTO MARIANO\n\n";
//printf ("Conteudo da variavel num : %d\n", num);
//printf ("Endereço da variavel num : %x \n", &num);
//printf ("Conteudo da variavel ponteiro ptr: %x", ptr);
cout << "Conteudo da variavel num : " << num;
cout << "\n\nEndereço da variavel num : " << &num;
cout << "\n\nConteudo da variavel ponteiro ptr : " <<ptr;
getch();
return(0);
}
Programa utilizando ponteiro
2019.2 16
SAÍDA
Programa utilizando ponteiro
2019.2 17
A "seta" consiste de um sinal de menos e um maior (->).
Para começar e deixar mais claro, definimos uma estrutura simples com dois campos. 
struct { 
int num; 
double valor; 
} Teste; 
O passo seguinte é definir um ponteiro para essa estrutura. 
struct Teste *Teste;
A partir do ponteiro podemos ter acesso a um campo da estrutura usando um seletor “->” (uma flecha).
Teste-> num = 10; 
Teste-> valor = 5.0; 
O mesmo resultado pode ser obtido com uso do deferenciador () e um ponto.
(*Teste).num = 10; 
(*Teste).valor = 5.0;
Operador Seta e 
Dereferenciador e um ponto
2019.2 18
#include <iostream>
using namespace std;
#include<conio.h>
typedef struct data Data; //PARA TRABALHAR COM DATA
struct data {
short dia;
short mes;
int ano;
};
int main (void){
Data data; //variável data do tipo struct data
Data *hoje; //ponteiro hoje para um tipo struct data
hoje = &data; //hoje aponta para o endereço de data
//dados sendo inseridos navariável data
hoje->dia = 27;
hoje->mes = 8;
hoje->ano = 2019;
//mostrando o que está gravado no endereço contido em hoje
cout << "\n\n\tPROFESSOR: EDIBERTO MARIANO - PONTEIRO\n\n"<<endl;
cout << "\tUsando o proprio ponteiro e uma seta (->) para indicar o membro\n\n"<<endl;
cout << "\tData registrada : ";
cout << hoje->dia <<"/"<< hoje->mes <<"/"<< hoje->ano << endl;
getch();
}
Programa usando o próprio ponteiro e uma seta (->) para 
indicar o membro
2019.2 19
SAÍDA
Programa usando o próprio ponteiro e uma seta (->) para 
indicar o membro.
2019.2 20
#include <iostream>
using namespace std;
#include<conio.h>
typedef struct data Data; //PARA TRABALHAR COM DATA
struct data {
short dia;
short mes;
int ano;
};
int main (void){
Data data; //variável data do tipo struct data
Data *hoje; //ponteiro hoje para um tipo struct data
hoje = &data; //hoje aponta para o endereço de data
//dados sendo inseridos na variável data
(*hoje).dia = 27;
(*hoje).mes = 8;
(*hoje).ano = 2019;
//mostrando o que está gravado no endereço contido em hoje
cout << "\n\n\tPROFESSOR: EDIBERTO MARIANO - PONTEIRO\n\n"<<endl;
cout << "\tData registrada : ";
cout << (*hoje).dia <<"/"<< (*hoje).mes <<"/"<< (*hoje).ano << endl;
getch();
}
Programa usando um dereferenciador entre parênteses e 
um ponto (.) para indicar o membro
2019.2 21
SAÍDA
Programa usando um dereferenciador entre parênteses e 
um ponto (.) para indicar o membro
2019.2 22
int *ptr;
ptr = &meu_array[0]; /* aponta nosso ponteiro, para o primeiro inteiro em nosso array */
Há duas formas de trabalhar com ponteiros para vetor.
1. Usar índices no ponteiro como se ele fosse um vetor:
2. Usar o que chamamos de aritmética de ponteiros. 
Ponteiros e Arrays
2019.2 23
#include<iostream>
using namespace std;
#include<conio.h>>
int main (void){
int vetor[2];
int *v; // ponteiro
v = vetor;
//USANDO INDICES NO PONTEIRO COMO SE ELE FOSSE UM VETOR
v[0] = 224;
v[1] = 768;
cout << "\n\n\tPROFESSOR: EDIBERTO MARIANO - PONTEIRO e ARRAY\n\n"<<endl;
cout << "\n\n\tUSANDO INDICES NO PONTEIRO COMO SE ELE FOSSE UM VETOR\n\n"<<endl;
//printf ("vetor[0] = %d\n", vetor[0]);
//printf ("vetor[1] = %d\n\n", vetor[1]);
cout << "\n\tvetor[0] = " << vetor[0];
cout << "\n\tvetor[1] = " << vetor[1];
//system ("pause");
getch();
}
Ponteiros e Arrays
1. Usar índices no ponteiro como se ele fosse um vetor:
2019.2 24
SAÍDA
Ponteiros e Arrays
1. Usar índices no ponteiro como se ele fosse um vetor:
2019.2 25
Aritmética de Ponteiros
Aritmética de ponteiros consiste em modificar o valor do ponteiro para ele indicar o próximo endereço de memória do vetor.
Exemplificando, seria algo como:
ponteiro = endereço do índice 0 do vetor;
*(ponteiro+indice1) = qualquer valor para ser gravado nesse índice;
*(ponteiro+indiceN) = qualquer valor para ser gravado nesse índice;
Ex.:
Se tivermos um ponteiro para um vetor de inteiro, quando formos calcular o terceiro espaço faremos *(ponteiro+3).
Internamente será calculado o seguinte → ponteiro + 3 * o tamanho de int (4 bytes).
Então, 3× 4 = 12 bytes.
ponteiro = 0x00001100;
ponteiro + 12 bytes;
novo ponteiro = 0x00001100C;
Apesar de ser uma conta simples, não precisamos nos preocupar com isso. Porque o próprio sistema cuida de executar este 
cálculo.
Ponteiros e Arrays
2. Usar o que chamamos de aritmética de ponteiros.
2019.2 26
#define MAX 3
int main (void){
int vetor [MAX], i, valor, *v;
v = &vetor[0];
cout << "\n\n\tPROFESSOR: EDIBERTO MARIANO - PONTEIRO e ARRAY"<<endl;
cout << "\n\n\tUSANDO ARITMETICA DE PONTEIROS"<<endl;
cout << "\n\tENTRADA DE DADOS\n"<<endl;
printf ("\tDigite um valor para ser gravado no :\n\n");
printf ("\tindice\tEndereco de Memoria\n");
for (i=0; i<MAX; i++) {
//printf ("\t[%d]\t%p\t\t-> ", i, (v+i));
cout << "\t" << i << "\t" << v+i << "\t : ";
cin >> valor;
getchar();
*(v+i) = valor; //valor é gravado no endereço apontado pelo ponteiro
}
system ("cls");
cout << "\n\n\tPROFESSOR: EDIBERTO MARIANO - PONTEIRO e ARRAY\n\n"<<endl;
cout << "\n\n\tUSANDO ARITMETICA DE PONTEIROS\n\n"<<endl;
cout << "\n\n\tSAIDA DE DADOS E VALORES GRAVADOS NO VETOR\n\n"<<endl;
//printf ("Os valores gravados no vetor foram:\n");
for (i=0; i<MAX; i++) {
//printf("vetor[%d], ponteiro (%p) = %d\n", i, (v+i), vetor[i]);
cout << "\tVetor [" << i << "]" <<" Ponteiro = " << v+i << " Valor = " << vetor[i] << "\n";
}
system ("pause");
}
Ponteiros e Arrays
2. Usar o que chamamos de aritmética de ponteiros.
2019.2 27
SAÍDAS
Ponteiros e Arrays
2. Usar o que chamamos de aritmética de ponteiros.
2019.2 28
++ incremento unitário
-- decremento unitário
Suponha que p é um ponteiro do tipo inteiro e suponha que o tipo inteiro na arquitetura de destino do exemplo 
sejam representados por 2 bytes cada. Considere o seguinte trecho de código:
int vet[10];
int *iptr;
iptr = vet;
iptr++;
Explicação
p++ simplesmente faz o ponteiro apontar para a posição seguinte
*(p++) nesse caso, faz um pós-incremento, então ele primeiro usa o valor apontado e depois de terminar a operação faz o 
ponteiro apontar para a posição seguinte.
caso fosse *(++p) ele incrementaria antes de usar o ponteiro.
*(p+5) utiliza o ponteiro 5 posições a frente, sem mexer no ponteiro.
(*p)+=4 soma ao valor apontado 4 unidades.
Ponteiros
Operandos unários
2019.2 29
#include <stdio.h>
#include <string.h>
int main() {
char *nome = "EDIBERTO";
int i = 0;
int *pi = &i;
/* Incremento por posicao*/
printf("\nEXIBINDO ARRAY INCREMENTANDO O PONTEIRO:\n\n");
for (i=0; i<strlen(nome);i++) {
printf("Caracter: %c | Endereco: %p , %d\n",*(nome+i),(nome+i),(nome+i));
}
/* Incremento por tipo de dado*/
printf("\n\nNumero: %d | Endereco: %p , %d\n",i,&i,&i);
printf("\n\nConteudo apontado pelo ponteiro: %d \nEndereco para onde o ponteiro
aponta: %p %d\n",*pi,pi,pi);
printf("\n\nIncrementando o ponteiro pelo tipo\n\n");
printf("%d , %d <-- Moveu %d bytes por que um int tem: %d bytes\n",i+1,(int)(pi+1),
(int)(pi+1)-(int)(pi),sizeof(int));
return 0;
}
Ponteiros
Operandos unários
2019.2 30
SAÍDA
Ponteiros
Operandos unários
2019.2 31
#include<iostream>
using namespace std;
int main() {
int x, *p, y;
x = 4; 
cout << x; //x = 4
p = &x; 
cout << "\nValor de p = " <<p; // 0x7ffcea5cb618 (varia a cada execução)
y = *p; 
cout << "\nValor de y = " <<y; // 4
y = 7; 
cout << "\nValor de *p = " <<*p; // 4
(*p)++;
cout << "\nValor de *p = " <<*p; // 5
cout << "\nValor de x = " <<x; // 5
(*p) = (*p) + y; 
cout << "\nValor de x = " <<x; // 5 + 7 = 12
return(0); 
}
Exemplo
Ponteiros
2019.2 32
EXERCÍCIO 01 – Codifique um programa em C++ que:
- Atribua via programa um valor inteiro à uma variável;
- Exiba o conteúdo da variável e o endereço de memória da mesma.
EXERCÍCIO 02 – Codifique um programa em C++ que:
- Atribua (leia) via teclado (console) um valor inteiro à uma variável;
- Exiba o conteúdo da variável e o endereço de memória da mesma.
EXERCÍCIO 03 – Codifique um programa em C++ que:
- Atribua (leia) via teclado (console) três valores inteiro;
- Após os valores informados, exiba-os na tela com seus respectivos endereços de
memória
Aula 04
Exercícios
2019.2 33
EXERCÍCIO 04 – Ao executarmos o seguinte código, qual resultado será apresentado 
na tela?
#include<iostream>
using namespace std;
int funcao (int *valor1, int *valor2) {
*valor1 = 50;
*valor2 = 200;
return 100;
}
int main() {
int *a, b;
a = &b;
b = 100;
funcao(a, a);
cout << *a;
cout <<" e "<< b;
}
Aula 04
Exercícios
2019.2 34
EXERCÍCIO 05 – O que acontece se o código abaixo for compilado em C++?
#include<iostream>
using namespace std;
int funcao (int valor1, int valor2) {
*valor1 = 50;
*valor2 = 200;
return 100;
}
int main() {
int *a, b;
a = &b;
b = 100;
funcao(a, a);
cout << *a;
cout <<" e "<< b;
}
Aula 04
Exercícios
2019.2 35
EXERCÍCIO 06 – Codifique um programa em C++ que:
Atribua (leia) via teclado (console) a data do seu nascimento (dia, mês e ano);
Após os valores informados, exiba-osna tela.
OBS. Utilize a struct data conforme abaixo, usando ponteiro e seta para indicar o membro da 
estrutura.
struct data {
short dia;
short mes;
int ano;
};
EXERCÍCIO 07 – Codifique um programa em C++ que:
Atribua (leia) via teclado (console) a data do seu nascimento (dia, mês e ano);
Após os valores informados, exiba-os na tela.
OBS. Utilize a struct data conforme abaixo, usando dereferenciador entre parênteses e um ponto (.) 
para indicar o membro da estrutura.
struct data {
short dia;
short mes;
int ano;
};
Aula 04
Exercícios
2019.2 36
EXERCÍCIO 08 – Dado o array descrito abaixo:
int A[10];
Crie dois ponteiros que apontem sucessivamente para as duas primeiras posições do array A.
EXERCÍCIO 09 – De acordo o código em C++ abaixo:
int vet[10];
int *iptr;
iptr = vet;
iptr++;
Descreva o que faz cada opção abaixo:
iptr++ 
*( iptr++)
*(++iptr) 
*( iptr+5)
(*iptr)+=4
Aula 04
Exercícios
2019.2 37
Aula 04
EXERCÍCIO 10 – Um apontador é uma variável que contém o endereço de outra variável. 
Apontadores são muito usados, em parte porque são, às vezes, a única forma de se 
expressar um processo de computação e, em parte, porque, normalmente, implicam um 
código mais compacto e eficiente que o obtido de outras formas. Considerando o uso de 
apontadores nas linguagens procedurais atuais, julgue os itens que se seguem com E se for 
errado e C se for certo.
( ) O uso de apontadores como argumentos de funções que realizem chamada por valor 
não permite alteração de seus conteúdos de memória na função.
( ) Com apontadores, é possível criar funções que retornem estruturas de dados 
complexas.
( ) Para recuperar o valor da variável apontada, basta que o apontador seja atribuído a 
uma variável de mesmo tipo.
( ) Arranjos de apontadores podem ser usados em funções que recebam como 
argumentos um número variável de cadeias de caracteres.
( ) Em geral, para que um arranjo seja percorrido por um ponteiro, para cada elemento 
do arranjo deve-se adicionar ao ponteiro o número de bytes que o elemento ocupa em 
memória
a) E - C - E - C - E
b) C - C - E - E - E
c) E - E - C - C - E
d) E - C - E - C - C
e) C - E - C - E - C
2019.2 38
Aula 04
EXERCÍCIO 11 – A respeito de Alocação Dinâmica de Memória, quais as vantagens no uso 
de representar os dados por encadeamento?
EXERCÍCIO 12 – Qual o valor de x no final do programa?
#include<iostream>
using namespace std;
int main() {
int x, *p, y;
x = 2; 
p = &x; 
y = *p; 
y = 5; 
(*p)++;
(*p) = (*p) - y; 
return(0); 
}

Outros materiais