Baixe o app para aproveitar ainda mais
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
Compartilhar