Prévia do material em texto
Programação Estruturada
Prof.ª: Priscilla Abreu
pbraz@unicarioca.edu.br
Disciplina – Programação Estruturada
Roteiro de aula:
• Objetivo da aula
– Ponteiros
• Conceito
• Manipulação
• Exercícios
2 Programação Estruturada
INTRODUÇÃO
3 Programação Estruturada
Armazenando informações
̶ Armazenamento de informação -> ocupa espaço;
̶ Declaração de variável -> alocação de espaço de
memória;
̶ Variável associada a um espaço de memória do
computador. Tal espaço de memória é representado por
um valor, seu endereço.
4 Programação Estruturada
Memória
1 byte
Armazenando informações
̶ Cada tipo de dado declarado em um programa ocupa um
tamanho diferente na memória do computador.
5
Tipo de Dado Tamanho
char 1 byte
int 4 bytes
float 4 bytes
Double 8 bytes
Memória
t
1
t e s t e \0
Instruções
Char x = ‘t’;
int y = 1;
char z[6] = ‘teste’;
Uso do comando sizeof() para
obter o tamanho que cada tipo de
dado ocupa.
Programação Estruturada
Armazenando informações
6 Programação Estruturada
Instruções
char x;
Memória
x
2000 2001 2002 2003 2004
x é associado
a um endereço Espaço de
memória
reservado
Endereço
Instruções
x = ‘t’;
char y = ‘a’;
Memória
x y
2000 2001 2002 2003 2004
O conteúdo ‘t’ é
armazenado no
endereço
Endereço
y é associado a um endereço,
um espaço de memória é reservado para o conteúdo de y
e o conteúdo de ‘a’ é armazenado no endereço.
t a
PONTEIROS
7 Programação Estruturada
O que é um ponteiro?
̶ Variável que armazena um endereço de memória.
̶ É um tipo de variável especial que armazena o
endereço de outra variável alocada na memória;
̶ Tem por função apontar para um endereço de
memória determinado.
8 Programação Estruturada
Por que usar ponteiros?
Os ponteiros são muito úteis e bastante utilizados nas
situações onde é necessário conhecer o endereço onde
está armazenada fisicamente uma variável e não
propriamente o seu conteúdo.
9 Programação Estruturada
Declarando um ponteiro
̶ Sintaxe da declaração de ponteiros:
tipo *nome_ponteiro;
̶ Declaração:
int x, *pt_x;
Variável x do tipo int e ponteiro *pt_x que
armazenará o endereço de uma variável do tipo int.
11 Programação Estruturada
Operadores de manipulação de ponteiros
Manipulação de ponteiros ocorre de duas maneiras:
̶ Por meio do endereço de uma variável;
̶ Por meio do conteúdo armazenado no endereço apontado
pelo ponteiro.
Operadores:
̶ Operador de endereço: &
̶ Operador de conteúdo: *
12 Programação Estruturada
Operadores de manipulação de ponteiros
̶ Operador de endereço (&)
Valor da variável ≠ endereço de memória
Função scanf()
scanf(“%d”, &num);
1. Leitura do buffer do teclado;
2. Transforma o valor lido em um valor inteiro;
3. Armazena o valor convertido no espaço físico
alocado no endereço da variável x.
13 Programação Estruturada
Operadores de manipulação de ponteiros
̶ Operador de endereço (&)
Indica o endereço de uma variável, que pode ser
impresso ou lido com printf e scanf a partir dos
operadores de conversão %x.
14 Programação Estruturada
Programa
#include <stdio.h>
int main(){
char x = ‘t’;
printf(“Conteúdo de x é: %c ”, x);
printf(“Endereço de x é: %x”, &x);
}
Memória
x
t
2000 2001 2002 2003 2004
Busca o conteúdo
Busca o endereço
Endereço
Operadores de manipulação de ponteiros
̶ Inicialização de um ponteiro
#include <stdio.h>
int main(){
int idade = 35;
int *pont_Id;
pont_Id = &idade;
printf("Valor da variável idade: %d\n", idade);
printf("Endereço da variável idade: %x\n", &idade);
printf("Valor da variável ponteiro pont_Id: %p", pont_Id);
return 0;
}
16 Programação Estruturada
Operadores de manipulação de ponteiros
̶ Inicialização de um ponteiro
̶ Ponteiros devem ser inicializados antes de serem usados, o
que pode ser feito na declaração ou através de uma
atribuição.
̶ Um ponteiro pode ser inicializado com um endereço ou
com o valor NULL. O valor NULL é uma constante definida
no arquivo <stdio.h> e significa que o ponteiro não aponta
para lugar nenhum.
17 Programação Estruturada
Operadores de manipulação de ponteiros
̶ Operador de conteúdo (*)
Utilizado na declaração de um ponteiro, mas também toda vez
que se deseja saber qual o valor contido no endereço
armazenado pelo ponteiro.
Endereço de um ponteiro: endereço físico alocado para essa
variável no momento da sua declaração;
Endereço armazenado pelo ponteiro: conteúdo do ponteiro
18 Programação Estruturada
Operadores de manipulação de ponteiros
̶ Operador de conteúdo (*)
19 Programação Estruturada
Programa
#include <stdio.h>
int main(){
char x = ‘t’, *p;
p = &x;
printf(“Conteúdo do ponteiro: %p”, p);
printf(“Conteúdo de x é: %c ”, x);
printf(“Conteúdo apontado: %d”, *p);
}
Memória
x P
t 2000
2000 2001 2002 2003
Busca o endereço
armazenado
Busca o conteúdo apontado pelo ponteiro
Busca o conteúdo de x
Operadores de manipulação de ponteiros
̶ Operador de conteúdo (*)
Através do operador de conteúdo, também é possível
atribuirmos um valor à variável apontada pelo ponteiro.
Exemplo:
int a = 5, *p;
p = &a;
printf(“a = %d”, a);
*p = 10;
printf(“a = %d”, a);
20 Programação Estruturada
Aritmética de ponteiros
É possível realizar operações de soma e subtração nos
ponteiros.
Ao somar o valor 1 a um ponteiro, o endereço contido
no ponteiro será modificado para o próximo endereço
de memória correspondente ao tipo de dado
especificado.
21 Programação Estruturada
Comparação de ponteiros
É possível comparar ponteiros em uma expressão
relacional. No entanto, só é possível comparar
ponteiros de mesmo tipo.
if (px == py) // se px aponta para o mesmo bloco que py ...
if (px > py) // se px aponta para um bloco posterior a py ...
if (px != py) // se px aponta para um bloco diferente de py ...
if (px == NULL) // se px é nulo...
22 Programação Estruturada
Exercícios
O programa (trecho de código) abaixo possui erros.
Qual(is)? Como deveriam ser?
void main() {
int x, *p;
x = 100;
p = x;
printf(“Valor de p: %d.\n”, *p);
}
23 Programação Estruturada
Exercícios
O programa (trecho de código) abaixo possui erros. Qual(is)?
Como deveriam ser?
void main() {
int x, *p;
x = 100;
p = x; /* p deveria receber o endereço de x, já que p é
um ponteiro (e x não). Ponteiros “armazenam” o endereço
para o qual eles apontam! O código correto seria: p = &x; */
printf(“Valor de p: %d.\n”, *p);
}
24 Programação Estruturada
Exercícios
Qual será a saída deste programa, supondo que i
ocupa o endereço 4094 na memória?
int main() {
int i=5, *p;
p = &i;
printf(“%p – %d – %d \n”, p, *p+2, 3*(*p));
}
25 Programação Estruturada
4094 - 7 - 15
Ponteiro e vetores
Na inicialização de um ponteiro com variáveis do tipo
vetor, matriz ou string não é preciso usar o operador &,
pois eles já são considerados ponteiros constantes.
Na atribuição será repassado o endereço alocado
referente à primeira posição da variável.
Exemplo:
char nome[34];
char *ponteiro;
ponteiro = nome;
26 Programação Estruturada
Ponteiro e vetores
#include <stdio.h>
int main (void){
float v[] = {1.0 , 2.0, 3.0, 4.0, 5.0, 6.0, 7.0};
int i;
float *p;
p = v;
for (i = 0; i < 7; i++)
printf ("%.1f ", p[i]);
printf("\n");
return 0;
}
27 Programação Estruturada
Funções – passagem de parâmetros
̶ A passagem de parâmetros entre as sub-rotinas se
dá de duas formas:
̶ Passagem por valor;
̶ Passagem por referência.
28 Programação Estruturada
Funções com passagem por referência
Passagem por referência:
permite a alteraçãodo valor de uma variável
necessária a passagem do endereço do argumento
para a função.
Uso de ponteiros.
29 Programação Estruturada
Funções com passagem por referência
#include <stdio.h>
void troca( int *pa, int *pb) {
int tmp = *pb;
*pb = *pa;
*pa = tmp;
}
int main (void){
int a=10, b=20;
troca(&a, &b);
printf(" a=%d b=%d\n", a, b);
}
30 Programação Estruturada
Funções com passagem por referência
#include <stdio.h>
void troca( int *pa, int *pb) {
int tmp = *pb;
*pb = *pa;
*pa = tmp;
}
int main (void){
int a=10, b=20;
troca(&a, &b);
printf(" a=%d b=%d\n", a, b);
}
31 Programação Estruturada
Funções com passagem por referência
#include <stdio.h>
void troca( int *pa, int *pb) {
int tmp = *pb;
*pb = *pa;
*pa = tmp;
}
int main (void){
int a=10, b=20;
troca(&a, &b);
printf(" a=%d b=%d\n", a, b);
}
32 Programação Estruturada
Funções com passagem por referência
#include <stdio.h>
void troca( int *pa, int *pb) {
int tmp = *pb;
*pb = *pa;
*pa = tmp;
}
int main (void){
int a=10, b=20;
troca(&a, &b);
printf(" a=%d b=%d\n", a, b);
}
33 Programação Estruturada
Funções com passagem por referência
#include <stdio.h>
void troca( int *pa, int *pb) {
int tmp = *pb;
*pb = *pa;
*pa = tmp;
}
int main (void){
int a=10, b=20;
troca(&a, &b);
printf(" a=%d b=%d\n", a, b);
}
34 Programação Estruturada
Funções com passagem por referência
#include <stdio.h>
void troca( int *pa, int *pb) {
int tmp = *pb;
*pb = *pa;
*pa = tmp;
}
int main (void){
int a=10, b=20;
troca(&a, &b);
printf(" a=%d b=%d\n", a, b);
}
35 Programação Estruturada
Funções com passagem por referência
#include <stdio.h>
void troca( int *pa, int *pb) {
int tmp = *pb;
*pb = *pa;
*pa = tmp;
}
int main (void){
int a=10, b=20;
troca(&a, &b);
printf(" a=%d b=%d\n", a, b);
}
36 Programação Estruturada
Funções com passagem por referência
#include <stdio.h>
void troca( int *pa, int *pb) {
int tmp = *pb;
*pb = *pa;
*pa = tmp;
}
int main (void){
int a=10, b=20;
troca(&a, &b);
printf(" a=%d b=%d\n", a, b);
}
37 Programação Estruturada
Exercício
Faça um programa que leia o lado de um quadrado e
implemente uma função que receba o lado, calcule e
retorne o perímetro e a área de um quadrado. Faça
todo o cálculo na mesma função e utilize apenas
variáveis locais e a passagem por referência.
38 Programação Estruturada
ALOCAÇÃO ESTÁTICA
X
ALOCAÇÃO DINÂMICA
39 Programação Estruturada
Alocação Estática
Alocação estática: o espaço de memória para as
variáveis é reservado no início da execução, não
podendo ser alterado depois.
int a; float n;
char c;
int b[20];
40 Programação Estruturada
Alocação Estática
A forma mais simples de estruturarmos um conjunto de
dados é por meio de vetores.
Definimos um vetor em C da seguinte forma:
int v[10];
Esta declaração diz que v é um vetor de inteiros
dimensionado com 10 elementos, isto é, reservamos um
espaço de memória contínuo para armazenar 10 valores
inteiros.
Assim, se cada int ocupa 4 bytes, a declaração reserva um
espaço de memória de 40 bytes.
41 Programação Estruturada
Alocação de memória em C
A linguagem C oferece meios de requisitarmos espaços de
memória em tempo de execução.
Uso da memória
(1) uso de variáveis globais: o espaço reservado existe enquanto
o programa estiver sendo executado.
(2) uso de variáveis locais: neste caso, o espaço existe apenas
enquanto a função que declarou a variável está sendo
executada, sendo liberado para outros usos quando a execução
da função termina.
(3) reservar memória requisitando ao sistema, em tempo de
execução, um espaço de um determinado tamanho.
42 Programação Estruturada
Alocação Dinâmica
Processo de solicitar e utilizar memória durante a execução de
um programa. É utilizada para que um programa utilize apenas a
memória necessária pra sua execução, sem desperdícios de
memória.
A alocação dinâmica de memória deve ser utilizada quando não
se sabe inicialmente, por algum motivo ou aplicação, quanto
espaço de memória será necessário para o armazenamento de
algum ou alguns valores.
De acordo com a linguagem de programação há funções próprias
para fazer o "pedido“ e “liberação” de memória.
− Aloca
− Libera
43 Programação Estruturada
Alocação Dinâmica
O espaço alocado dinamicamente permanece
reservado até que explicitamente seja liberado pelo
programa. Por isso, podemos alocar dinamicamente um
espaço de memória numa função e acessá-lo em outra.
A partir do momento que liberarmos o espaço, ele
estará disponibilizado para outros usos e não podemos
mais acessá-lo. Se o programa não liberar um espaço
alocado, este será automaticamente liberado quando a
execução do programa terminar.
44 Programação Estruturada
Alocação de memória em C
Uso da memória
45 Programação Estruturada
Alocação de memória em C
Uso da memória
46 Programação Estruturada
Alocação Estática x Alocação Dinâmica
Funções de alocação de memória em C:
• void * malloc(int qty_bytes_alloc);
• void * calloc(int qtd, int size);
• void * realloc(void * pointer, int new_size);
• free( void * pointer);
47 Programação Estruturada
Alocação Estática x Alocação Dinâmica
Função “malloc”:
– recebe como parâmetro o número de bytes que
se deseja alocar
– retorna um ponteiro genérico para o endereço
inicial da área de memória alocada, se houver
espaço livre:
– retorna um endereço nulo, se não houver espaço
livre:
• representado pelo símbolo NULL
48 Programação Estruturada
Alocação Estática x Alocação Dinâmica
Função “calloc”:
void *calloc (int num, int size);
- Aloca uma quantidade de memória igual a num * size;
- Inicializa os espaços de memória com o valor zero;
• Exemplo:
• int *v;
• v = (int *) calloc(10 , sizeof(int ));
49 Programação Estruturada
Alocação Estática x Alocação Dinâmica
Função “sizeof”:
– retorna o número de bytes ocupado por um tipo
Função “free”:
– recebe como parâmetro o ponteiro da memória a ser
liberada
• a função free deve receber um endereço de memória
que tenha sido alocado dinamicamente.
50 Programação Estruturada
Exemplo:
Alocação dinâmica de um vetor de inteiros com 10
elementos
• malloc retorna o endereço da área alocada para
armazenar valores inteiros
• ponteiro de inteiro recebe endereço inicial do espaço
alocado
int *v;
v = (int *) malloc(10 * sizeof(int ));
51 Programação Estruturada
Exemplo:
52 Programação Estruturada
Exemplo:
̶ v armazena endereço inicial de uma área contínua de
memória suficiente para armazenar 10 valores
inteiros
̶ v pode ser tratado como um vetor declarado
estaticamente
̶ v aponta para o inicio da área alocada
̶ v[0] acessa o espaço para o primeiro elemento
̶ v[1] acessa o segundo
̶ .... até v[9].
53 Programação Estruturada
Exemplo:
̶ tratamento de erro após chamada a malloc
̶ imprime mensagem de erro
̶ aborta o programa (com a função exit)
54 Programação Estruturada
Alocação Dinâmica
̶ A partir de agora é possível fazer a seguinte
implementação:
Escreva um programa em C que solicita ao usuário um
número n e então lê um vetor de n notas e calcula a
média aritmética.
– Usar alocação dinâmica do vetor
– Liberar a memória ao final
55 Programação Estruturada
Exemplo
#include <stdio.h>
int main (void){
float *v, media, soma=0.0; int qtde,i;
printf("Informe quantas notas que deseja armazenar:");
scanf("%d", &qtde);
v = (float*) malloc(qtde*sizeof(float));
56 Programação Estruturada
Exemplo (continuação)
for (i=0; i<qtde;i++){
printf("Informe a nota: ");
scanf("%f", &v[i]);
soma = soma + v[i];
}
media = soma / qtde;
printf("Média: %.1f\n", media);
free(v);
}
57 Programação Estruturada
AUMENTANDO O ESPAÇO ALOCADO
#include <stdio.h>
int main (void){
float *v;
float soma=0.0, media;
int qtde,i, qt2;
printf("Informe quantas notas deseja armazenar:");
scanf("%d", &qtde);
v = (float*) malloc(qtde*sizeof(float));
58 Programação Estruturada
AUMENTANDO O ESPAÇO ALOCADO
for (i=0; i<qtde;i++){
printf("Informe a nota: ");
scanf("%f", &v[i]);
soma = soma + v[i];
}
media = soma / qtde;
printf("Média: %.1f\n", media);
59 Programação Estruturada
AUMENTANDO O ESPAÇO ALOCADO
printf(“Quantidade de notas que deseja acrescentar - Digite 0 caso não
deseje.");
scanf("%d",&qt2);
if (qt2>0){
v = (float*) realloc(v, (qtde+qt2)*sizeof(float));
if (v){
for (i=qtde;i<(qtde+qt2);i++){
printf("Informe a nota: ");
scanf("%f", &v[i]);
soma=soma+v[i];
}
media = soma / (qtde+qt2);
printf("Nova média: %.1f\n", media);
}
}
}
60 Programação Estruturada
MODIFICANDO O ESPAÇO ALOCADO
Realloc
(tipo*) realloc( tipo *apontador, int novo_tamanho)
int *x, i;
x = (int *) malloc (200 * sizeof(int));
for (i = 0; i<200; i++){
printf(“Valor: ”); scanf(&x[i]);
}
x = (int *) realloc (x, 400 * sizeof(int));
x = (int *) realloc (x, 100 * sizeof(int));
free(x);
61 Programação Estruturada
MODIFICANDO O ESPAÇO ALOCADO
Realloc
62 Programação Estruturada
int *x, i;
x = (int *) malloc (200 * sizeof(int));
for (i = 0; i<200; i++){
printf(“Valor: ”); scanf(&x[i]);
}
x = (int *) realloc (x, 400 * sizeof(int));
x = (int *) realloc (x, 100 * sizeof(int));
free(x);
Exemplo – Alocação Dinâmica
#include <stdio.h>
struct ST_DADOS
{
char nome[40];
float salario;
/* estrutura dentro de uma estrutura */
struct nascimento
{
int ano;
int mes;
int dia;
} dt_nascimento;
};
63 Programação Estruturada
Exemplos
int main(void){
struct ST_DADOS * p;
p = (struct ST_DADOS *) malloc(sizeof(struct ST_DADOS));
if (p){
printf("\nEntre com o nome ->");
scanf("%s", p->nome);
printf("Entre com o salario ->");
scanf("%f", &p->salario);
printf("Entre com o nascimento ->");
scanf("%d%d%d", &p->dt_nascimento.dia,&p->
dt_nascimento.mes, &p->dt_nascimento.ano);
}
64 Programação Estruturada
Exemplos
printf("\n===== Dados digitados ====");
printf("\nNome = %s", p->nome);
printf("\nSalario = %f", p->salario);
printf("\nNascimento = %d/%d/%d\n",
p->dt_nascimento.dia,p->dt_nascimento.mes,
p->dt_nascimento.ano);
free(p);
system(“Pause”);
}
65 Programação Estruturada
Alocação Dinâmica
Através desse modo de alocação dinâmica,
conseguimos alocar espaços de memória em tempo de
execução e modificar o espaço alocado, também em
tempo de execução.
No entanto, todo o espaço alocado dinamicamente
reservou um bloco de memória com endereços
sequenciais, que foram manipulados como vetores.
66 Programação Estruturada
DÚVIDAS ?
67 Programação Estruturada