A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Capítulo VIII – Subprogramação 8.1 – Introdução 8.2 – Escopo de validade de declarações 8.3 – Parâmetros e passagem de argumentos 8.4 – Prototipação de.

Apresentações semelhantes


Apresentação em tema: "Capítulo VIII – Subprogramação 8.1 – Introdução 8.2 – Escopo de validade de declarações 8.3 – Parâmetros e passagem de argumentos 8.4 – Prototipação de."— Transcrição da apresentação:

1 Capítulo VIII – Subprogramação 8.1 – Introdução 8.2 – Escopo de validade de declarações 8.3 – Parâmetros e passagem de argumentos 8.4 – Prototipação de subprogramas 8.5 – Classes de alocação 8.6 – Recursividade

2 8.3 – Parâmetros e Passagem de Argumentos – Importância do uso de parâmetros É comum subprogramas atuarem sobre um determinado valor ou uma determinada variável para produzir um resultado ou realizar uma tarefa É comum subprogramas atuarem sobre um determinado valor ou uma determinada variável para produzir um resultado ou realizar uma tarefa Exemplos: Exemplos: Calcular o fatorial do valor guardado numa variável Calcular o fatorial do valor guardado numa variável Ordenar os elementos de um vetor Ordenar os elementos de um vetor Trocar os valores de duas variáveis entre si Trocar os valores de duas variáveis entre si

3 Variáveis globais poderiam ser usadas Variáveis globais poderiam ser usadas Nos exemplos anteriores: Nos exemplos anteriores: O valor cujo fatorial se deseja estaria numa variável global O valor cujo fatorial se deseja estaria numa variável global O vetor a ser ordenado seria global O vetor a ser ordenado seria global As variáveis para a troca de valores seriam também globais As variáveis para a troca de valores seriam também globais Mas, e se forem muitos(as): Mas, e se forem muitos(as): As variáveis ou as expressões das quais se quer calcular o fatorial? As variáveis ou as expressões das quais se quer calcular o fatorial? Os vetores a serem ordenados? Os vetores a serem ordenados? Os pares de variáveis a trocarem entre si seus valores? Os pares de variáveis a trocarem entre si seus valores? Antes de cada chamada, as variáveis globais deveriam ser carregadas com os alvos do subprograma Incômodo!!!

4 Para evitar esse carregamento a cada chamada, usam-se parâmetros e argumentos Para evitar esse carregamento a cada chamada, usam-se parâmetros e argumentos Como já foi visto, na chamada de um subprograma, os valores dos argumentos são calculados e armazenados cada um em seu respectivo parâmetro Como já foi visto, na chamada de um subprograma, os valores dos argumentos são calculados e armazenados cada um em seu respectivo parâmetro Parâmetro é uma variável local especial de um subprograma, também automática, distinta de suas outras variáveis locais Parâmetro é uma variável local especial de um subprograma, também automática, distinta de suas outras variáveis locais O subprograma então realiza sua tarefa, atuando diretamente sobre seus parâmetros O subprograma então realiza sua tarefa, atuando diretamente sobre seus parâmetros O programa do número de combinações usa parâmetros e argumentos, dispensando variáveis globais O programa do número de combinações usa parâmetros e argumentos, dispensando variáveis globais

5 8.3.2 – Modos de passagem de argumentos As linguagens tradicionais de programação apresentam dois importantes modos de passagem de argumentos aos respectivos parâmetros: As linguagens tradicionais de programação apresentam dois importantes modos de passagem de argumentos aos respectivos parâmetros: Passagem por valor Passagem por valor Passagem por referência Passagem por referência Passagem por valor: o argumento é o valor de uma expressão ou de uma variável, valor esse calculado e carregado no parâmetro Passagem por valor: o argumento é o valor de uma expressão ou de uma variável, valor esse calculado e carregado no parâmetro Passagem por referência: o argumento deve ser uma variável, sendo que o respectivo parâmetro é alocado coincidindo com o endereço da mesma Passagem por referência: o argumento deve ser uma variável, sendo que o respectivo parâmetro é alocado coincidindo com o endereço da mesma

6 Exemplo: passagem de argumentos em Pascal program ppp; var a, b: integer; procedure xxx (x: integer; var y: integer); begin x := x + 3; y := y + x; end;begin a := 10; b := 20; xxx (a, b); write (a =, a, ; b =, b); end. Comandos do programa ppp Procedimento xxx embutido em ppp A palavra var antes da declaração de y sinaliza que a passagem é por referência

7 Seja a execução deste programa: program ppp; var a, b: integer; procedure xxx (x: integer; var y: integer); begin x := x + 3; y := y + x; end;begin a := 10; b := 20; xxx (a, b); write (a =, a, ; b =, b); end. ? a ? b

8 program ppp; var a, b: integer; procedure xxx (x: integer; var y: integer); begin x := x + 3; y := y + x; end;begin a := 10; b := 20; xxx (a, b); write (a =, a, ; b =, b); end. ? a ? b 10 a 20 b

9 Chamada da procedure xxx: program ppp; var a, b: integer; procedure xxx (x: integer; var y: integer); begin x := x + 3; y := y + x; end;begin a := 10; b := 20; xxx (a, b); write (a =, a, ; b =, b); end. 10 a 20 b

10 Alocação dos parâmetros e passagem de argumentos: program ppp; var a, b: integer; procedure xxx (x: integer; var y: integer); begin x := x + 3; y := y + x; end;begin a := 10; b := 20; xxx (a, b); write (a =, a, ; b =, b); end. 10 a 20 bx 10 x y O valor de a foi copiado em x A variável y foi alocada coincidindo com b

11 program ppp; var a, b: integer; procedure xxx (x: integer; var y: integer); begin x := x + 3; y := y + x; end;begin a := 10; b := 20; xxx (a, b); write (a =, a, ; b =, b); end. 10 a 20 bx 10 x y

12 program ppp; var a, b: integer; procedure xxx (x: integer; var y: integer); begin x := x + 3; y := y + x; end;begin a := 10; b := 20; xxx (a, b); write (a =, a, ; b =, b); end. 10 a 20 bx 13 x y

13 program ppp; var a, b: integer; procedure xxx (x: integer; var y: integer); begin x := x + 3; y := y + x; end;begin a := 10; b := 20; xxx (a, b); write (a =, a, ; b =, b); end. 10 a 20 bx 13 x y

14 program ppp; var a, b: integer; procedure xxx (x: integer; var y: integer); begin x := x + 3; y := y + x; end;begin a := 10; b := 20; xxx (a, b); write (a =, a, ; b =, b); end. 10 a 33 bx 13 x y

15 Desalocação dos parâmetros: program ppp; var a, b: integer; procedure xxx (x: integer; var y: integer); begin x := x + 3; y := y + x; end;begin a := 10; b := 20; xxx (a, b); write (a =, a, ; b =, b); end. 10 a 33 bx 13 x y

16 program ppp; var a, b: integer; procedure xxx (x: integer; var y: integer); begin x := x + 3; y := y + x; end;begin a := 10; b := 20; xxx (a, b); write (a =, a, ; b =, b); end. 10 a 33 b a = 10; b = 33 No vídeo a não foi alterada (por valor) b foi alterada (por referência)

17 Quando se deseja que o argumento sofra alterações dentro do subprograma chamado: usar passagem por referência Quando se deseja que o argumento sofra alterações dentro do subprograma chamado: usar passagem por referência Quando o subprograma mudar o valor de um parâmetro, mas não se deseja que isso altere o valor do argumento de chamada: usar passagem por valor Quando o subprograma mudar o valor de um parâmetro, mas não se deseja que isso altere o valor do argumento de chamada: usar passagem por valor Quando um subprograma não altera o valor de um parâmetro, pode-se usar os dois tipos de passagem Quando um subprograma não altera o valor de um parâmetro, pode-se usar os dois tipos de passagem Se o parâmetro for uma variável estruturada (matriz ou estrutura), pode-se economizar memória usando passagem por referência Se o parâmetro for uma variável estruturada (matriz ou estrutura), pode-se economizar memória usando passagem por referência O parâmetro correspondente é alocado numa região já utilizada pelo programa O parâmetro correspondente é alocado numa região já utilizada pelo programa

18 A Linguagem C só trabalha com passagem por valor A Linguagem C só trabalha com passagem por valor A passagem por referência é simulada por argumentos do tipo endereço e parâmetros do tipo ponteiro A passagem por referência é simulada por argumentos do tipo endereço e parâmetros do tipo ponteiro Isso é visto logo a seguir Isso é visto logo a seguir

19 8.3.3 – Passagem por valor em C A função destinada ao cálculo de fatorial vista neste capítulo utiliza passagem por valor A função destinada ao cálculo de fatorial vista neste capítulo utiliza passagem por valor O valor do argumento é calculado e depositado no parâmetro O valor do argumento é calculado e depositado no parâmetro Depois da execução, mesmo que função mudasse o valor desse parâmetro, as variáveis envolvidas no cálculo dos argumentos não sofrem alteração Depois da execução, mesmo que função mudasse o valor desse parâmetro, as variáveis envolvidas no cálculo dos argumentos não sofrem alteração

20 Numa chamada de função aparece primeiramente seu nome e, a seguir, entre parêntesis, sua lista de argumentos Numa chamada de função aparece primeiramente seu nome e, a seguir, entre parêntesis, sua lista de argumentos Essa lista deverá ser vazia se a função não tiver parâmetros, mas o uso dos parêntesis é obrigatório Essa lista deverá ser vazia se a função não tiver parâmetros, mas o uso dos parêntesis é obrigatório Os argumentos devem ser em mesmo número que os parâmetros e devem ser compatíveis com os mesmos Os argumentos devem ser em mesmo número que os parâmetros e devem ser compatíveis com os mesmos Caso um argumento seja o nome de uma variável, apenas seu valor é transmitido ao parâmetro Caso um argumento seja o nome de uma variável, apenas seu valor é transmitido ao parâmetro Depois da execução, o valor dessa variável não terá sofrido nenhuma alteração Depois da execução, o valor dessa variável não terá sofrido nenhuma alteração

21 Exemplo: seja o programa Exemplo: seja o programa #include #include void ff (int a) { a += 1; printf ("Durante ff, a = %d\n", a); printf ("Durante ff, a = %d\n", a);} void main ( ) { int a = 5; printf ("Antes de ff, a = %d\n", a); printf ("Antes de ff, a = %d\n", a); ff (a); printf ("Depois de ff, a = %d\n", a); printf ("Depois de ff, a = %d\n", a); printf("\n\Digite algo para encerrar: "); printf("\n\Digite algo para encerrar: "); getch(); getch();} Antes de ff, a = 5 Durante ff, a = 6 Depois de ff, a = 5 Digite algo para encerrar: Resultado

22 8.3.4 – Passagem por referência em C Às vezes, é desejável que a variável argumento seja alterada conforme a mudança sofrida pelo parâmetro correspondente Às vezes, é desejável que a variável argumento seja alterada conforme a mudança sofrida pelo parâmetro correspondente Ao invés de passar o seu valor, passa-se o seu endereço Ao invés de passar o seu valor, passa-se o seu endereço A seguir, um programa ilustrativo para trocar os valores de duas variáveis da função main A seguir, um programa ilustrativo para trocar os valores de duas variáveis da função main

23 Exemplo: seja o programa Exemplo: seja o programa #include #include void trocar (int *p, int *q){ int aux; aux = *p; *p = *q; *q = aux; } int main ( ) { int i = 3, j = 8; printf ("Antes de trocar, i = %d; j = %d\n", i, j); trocar(&i, &j); printf ("Depois de trocar, i = %d; j = %d\n", i, j); printf("\n\Digite algo para encerrar: "); printf("\n\Digite algo para encerrar: "); getch(); getch();} Seja sua execução:

24 #include #include void trocar (int *p, int *q){ int aux; aux = *p; *p = *q; *q = aux; } int main ( ) { int i = 3, j = 8; printf ("Antes de trocar, i = %d; j = %d\n", i, j); trocar(&i, &j); printf ("Depois de trocar, i = %d; j = %d\n", i, j); printf("\n\Digite algo para encerrar: "); printf("\n\Digite algo para encerrar: "); getch(); getch();} 3 i 8 j Seja sua execução:

36 2.A conjectura de Goldbach diz que todo número inteiro, par, maior que 2, é a soma de dois números primos. Computadores têm sido muito usados para testar essa conjectura e nenhum contra-exemplo foi encontrado até agora. a)Escrever uma função que receba como argumento por valor um número inteiro positivo e que retorne 1, se tal número for primo, ou então zero, em caso contrário. b)Escrever um programa principal para comprovar que tal conjectura é verdadeira dentro de um intervalo lido, no campo dos inteiros maiores que 2, usando obrigatoriamente como subprograma a função elaborada no item a deste exercício. Por exemplo, se o intervalo lido for [700, 1100], o programa pedido deve ser produzir no vídeo um resultado semelhante ao do próximo slide

37 No intervalo [ 700, 1100 ], todo número par é a soma de dois primos, a saber: No intervalo [ 700, 1100 ], todo número par é a soma de dois primos, a saber: 700 = = = = =

38 Capítulo VIII – Subprogramação 8.1 – Introdução 8.2 – Escopo de validade de declarações 8.3 – Parâmetros e passagem de argumentos 8.4 – Prototipação de subprogramas 8.5 – Classes de alocação 8.6 – Recursividade

39 8.4 – Prototipação de Subprogramas Nos programas em C, funções devem ser declaradas antes de serem invocadas Nos programas em C, funções devem ser declaradas antes de serem invocadas Há uma diferença entre declarar e definir uma função Há uma diferença entre declarar e definir uma função Declarar: dizer o nome da função, o tipo de seus parâmetros e o tipo do valor por ela retornado Declarar: dizer o nome da função, o tipo de seus parâmetros e o tipo do valor por ela retornado Definir: programar a função, ou seja, declará-la, estabelecer suas declarações locais e seus comandos Definir: programar a função, ou seja, declará-la, estabelecer suas declarações locais e seus comandos Até agora: declaração das funções no ato de sua definição Até agora: declaração das funções no ato de sua definição

40 Há situações em que é interessante ou até necessário que uma função seja invocada antes de ser definida Há situações em que é interessante ou até necessário que uma função seja invocada antes de ser definida É o caso de programas recursivos, que são assuntos do último tópico deste capítulo É o caso de programas recursivos, que são assuntos do último tópico deste capítulo Exemplo: recursividade indireta: - F2 invoca F1 - F1 invoca F2 antes da declaração de F2 - O compilador não aceitará - Invertidas as funções, o problema continua int F1 (int a, float x) { chamada de F2() } int F2 (float y, char c ) { chamada de F1() }

41 Solução: Protótipos para funções Protótipo de uma função: é a declaração da função feita separadamente de sua definição No ponto em que F1 invoca F2, essa última já está declarada acima Não é necessário colocar os nomes dos parâmetros, mas somente os tipos Na definição, todos os tipos devem ser os mesmos do protótipo int F1 (int a, float x) { chamada de F2() } int F2 (float y, char c ) { chamada de F1() } int F2 (float, char); int F1 (int a, float x) { chamada de F2() } int F2 (float y, char c ) { chamada de F1() } Forma geral de um protótipo: Tipo Nome (lista dos tipos dos parâmetros);

42 Protótipos para as funções usadas nos programas deste capítulo: Protótipos para as funções usadas nos programas deste capítulo: int fat (int); int fat (int); void sss (void); void sss (void); void ff (void); void ff (void); void ff (int); void ff (int); void trocar (int *, int *); void trocar (int *, int *); Quando a função não tem parâmetros, coloca-se void entre parêntesis Quando a função não tem parâmetros, coloca-se void entre parêntesis Quando o parâmetro é um ponteiro, coloca-se o asterisco * depois do tipo Quando o parâmetro é um ponteiro, coloca-se o asterisco * depois do tipo

43 Pode-se adquirir o hábito de fazer protótipos para todas a funções auxiliares dos programas Pode-se adquirir o hábito de fazer protótipos para todas a funções auxiliares dos programas Eles podem ser colocados no início, juntamente com as declarações globais Eles podem ser colocados no início, juntamente com as declarações globais Então a ordem das definições das funções pode ser qualquer Então a ordem das definições das funções pode ser qualquer Programa Diretivas de pré- processamento Declarações globais Funções auxiliares Função main Protótipos das funções

44 Pode-se organizar o programa de forma a colocar primeiramente a função main Pode-se organizar o programa de forma a colocar primeiramente a função main Depois vêm aquelas invocadas pela main; depois, aquelas invocadas por essas últimas Depois vêm aquelas invocadas pela main; depois, aquelas invocadas por essas últimas E assim por diante E assim por diante Essa ordenação é interessante ao se utilizar a metodologia top-down para o desenvolvimento de programas Essa ordenação é interessante ao se utilizar a metodologia top-down para o desenvolvimento de programas Programa Diretivas de pré- processamento Declarações globais Função main Funções auxiliares Protótipos das funções No capítulo sobre ponteiros serão vistos protótipos de funções com parâmetros do tipo variáveis indexadas, estruturas e funções

45 Capítulo VIII – Subprogramação 8.1 – Introdução 8.2 – Escopo de validade de declarações 8.3 – Parâmetros e passagem de argumentos 8.4 – Prototipação de subprogramas 8.5 – Classes de alocação 8.6 – Recursividade

46 8.5 – Classes de Alocação Generalidades Toda variável e função em C tem, além do tipo, outro atributo, relacionado com a forma de ser alocada durante a execução do programa Toda variável e função em C tem, além do tipo, outro atributo, relacionado com a forma de ser alocada durante a execução do programa Esse atributo é a classe de alocação Esse atributo é a classe de alocação

47 Há 4 classes de alocação de variáveis e funções, a saber: Há 4 classes de alocação de variáveis e funções, a saber: variáveis automáticas, externas, estáticas e em registradores As palavras reservadas para elas são respectivamente As palavras reservadas para elas são respectivamente auto, extern, static e register. Essas palavras são colocadas antes do tipo, numa declaração de variáveis e função Essas palavras são colocadas antes do tipo, numa declaração de variáveis e função Exemplos: Exemplos: extern int i; static float a; register int j;

48 Como já visto, as variáveis automáticas só ocupam espaço na memória quando seu bloco de declaração está no ar Como já visto, as variáveis automáticas só ocupam espaço na memória quando seu bloco de declaração está no ar Todas as variáveis locais vistas até agora neste capítulo são automáticas Todas as variáveis locais vistas até agora neste capítulo são automáticas Quando não se especifica a classe de uma variável local, o compilador entende que ela é automática Quando não se especifica a classe de uma variável local, o compilador entende que ela é automática Então, como já foi visto: Então, como já foi visto: int a, b; equivale a auto int a, b; Por essa razão, a palavra reservada auto é raramente usada nos programas Por essa razão, a palavra reservada auto é raramente usada nos programas

49 8.5.2 – Variáveis externas Em C, toda variável declarada fora do escopo de qualquer função, ou seja, toda variável global, pertence à classe das variáveis externas Em C, toda variável declarada fora do escopo de qualquer função, ou seja, toda variável global, pertence à classe das variáveis externas Ela ocupa espaço de memória durante toda a execução do programa Ela ocupa espaço de memória durante toda a execução do programa A palavra extern pode ser usada em sua declaração, mas na maioria dos casos é dispensável A palavra extern pode ser usada em sua declaração, mas na maioria dos casos é dispensável Se int a = 1; for uma declaração global então ela equivale a extern int a = 1; Se int a = 1; for uma declaração global então ela equivale a extern int a = 1;

50 O principal uso da palavra extern se dá em programas divididos em mais de um arquivo O principal uso da palavra extern se dá em programas divididos em mais de um arquivo Muitas vezes é desejável compilar cada arquivo separadamente Muitas vezes é desejável compilar cada arquivo separadamente Exemplo: seja o programa a seguir, dividido em dois arquivos arq1.c e arq2.c Exemplo: seja o programa a seguir, dividido em dois arquivos arq1.c e arq2.c #include #include "arq2.c" int a = 1, b = 2, c = 3; void main ( ) { printf ("%3d\n", f( )); printf ("%3d%3d%3d\n", a, b, c); getch(); } int f () { extern int a; int b, c; a = b = c = 4; return (a + b + c); } arq1.carq2.c

51 Na compilação separada do arquivo arq2.c, a declaração Na compilação separada do arquivo arq2.c, a declaração extern int a; indica que a variável a é global e está declarada em outro arquivo Para uma compilação conjunta, esta declaração é dispensável Para uma compilação conjunta, esta declaração é dispensável #include #include "arq2.c" int a = 1, b = 2, c = 3; void main ( ) { printf ("%3d\n", f()); printf ("%3d%3d%3d\n", a, b, c); getch(); } int f () { extern int a; int b, c; a = b = c = 4; return (a + b + c); } arq1.carq2.c No vídeo

52 A habilidade em compilar arquivos separadamente é importante ao ser escrever grandes programas A habilidade em compilar arquivos separadamente é importante ao ser escrever grandes programas O código-fonte desses programas costuma ser organizado em diversos arquivos O código-fonte desses programas costuma ser organizado em diversos arquivos Cada arquivo pode conter uma ou mais funções, ou somente declarações globais, ou protótipos de funções, etc. Cada arquivo pode conter uma ou mais funções, ou somente declarações globais, ou protótipos de funções, etc. Ocorrendo erros de compilação, só os arquivos com erros precisam ser re-compilados Ocorrendo erros de compilação, só os arquivos com erros precisam ser re-compilados Os arquivos corretos são dispensados disso e, sendo numerosos, ganha-se tempo com essa dispensa Os arquivos corretos são dispensados disso e, sendo numerosos, ganha-se tempo com essa dispensa

53 8.5.3 – Comunicação entre funções Funções se comunicam entre si através de variáveis globais, parâmetros por valor, parâmetros por referência e valores retornados Funções se comunicam entre si através de variáveis globais, parâmetros por valor, parâmetros por referência e valores retornados int a; void main () { int b, c, d; a = 10; b = 20; c = 30; d = ff (b, &c); printf (- - -, a, b, c, d); } int ff (int x, int *y) { int z; z = x + a + *y; a = 1; *y = 2; return z; } a bc d xyz Exemplo

54 Variáveis globais: comunicação nos 2 sentidos Variáveis globais: comunicação nos 2 sentidos Parâmetros por valor: da invocadora para a invocada Parâmetros por valor: da invocadora para a invocada Parâmetros por referência: comunicação nos 2 sentidos Parâmetros por referência: comunicação nos 2 sentidos Valores retornados: da invocada para a invocadora Valores retornados: da invocada para a invocadora int a; void main () { int b, c, d; a = 10; b = 20; c = 30; d = ff (b, &c); printf (- - -, a, b, c, d); } int ff (int x, int *y) { int z; z = x + a + *y; a = 1; *y = 2; return z; } a bc d xyz retorno

55 Variáveis globais dificultam a modularidade e portabilidade das funções Variáveis globais dificultam a modularidade e portabilidade das funções Parâmetros e valores retornados são decididamente preferíveis quando isso é desejado Parâmetros e valores retornados são decididamente preferíveis quando isso é desejado Analogia: aparelho de som para automóveis Analogia: aparelho de som para automóveis Má portabilidade: com muitos cabos elétricos do carro a ele conectados, haverá dificuldade para retirá-lo e colocá- lo em outro carro Má portabilidade: com muitos cabos elétricos do carro a ele conectados, haverá dificuldade para retirá-lo e colocá- lo em outro carro Boa portabilidade: se não houver cabos a ele conectados, essa dificuldade é nula Boa portabilidade: se não houver cabos a ele conectados, essa dificuldade é nula

56 Uma função com variáveis globais a ser disponibilizada para a comunidade exige de quem vai utilizá-la: Uma função com variáveis globais a ser disponibilizada para a comunidade exige de quem vai utilizá-la: Conhecimento da existência dessas variáveis Conhecimento da existência dessas variáveis Adição das mesmas ao conjunto de variáveis globais de seu programa Adição das mesmas ao conjunto de variáveis globais de seu programa Uma função sem variáveis globais é muito mais simples de ser reutilizada Uma função sem variáveis globais é muito mais simples de ser reutilizada

57 Há casos no entanto, em que o uso de variáveis globais é providencial Há casos no entanto, em que o uso de variáveis globais é providencial Um grande programa com inúmeros subprogramas atuando numa mesma grande base de dados Um grande programa com inúmeros subprogramas atuando numa mesma grande base de dados As variáveis dessa base podem ser globais As variáveis dessa base podem ser globais Não haverá a necessidade de, na maioria das chamadas de subprogramas, fazer passagem de argumentos Não haverá a necessidade de, na maioria das chamadas de subprogramas, fazer passagem de argumentos Evita-se transporte desnecessário de informações entre os subprogramas, mesmo que seja apenas de ponteiros Evita-se transporte desnecessário de informações entre os subprogramas, mesmo que seja apenas de ponteiros

58 Exemplo: um compilador Analisador léxico Analisador sintático Analisador semântico Gerador de código intermediário Otimizador de código intermediário Gerador de código objeto while (i < nn) i = i + j; Programa-fonte (caracteres) Sequência de átomos Árvore sintática while i < nni = i + j i j int Tabela de símbolos while(i

59 Analisador léxico Analisador sintático Analisador semântico Gerador de código intermediário Otimizador de código intermediário Gerador de código objeto while (i < nn) i = i + j; Programa-fonte (caracteres) load i R1: sub nn JZ R2 load i add j st i J R1 R2: Código objeto Seria incômodo e dispendioso o trânsito dos átomos, da árvore sintática, da tabela de símbolos e do código intermediário pelas funções do compilador Fica a cargo do programador escolher o melhor modo de comunicação entre os módulos de seu programa

60 8.5.4 – Variáveis em registradores A Linguagem C permite que o programador expresse sua preferência por registradores, na alocação de uma variável A Linguagem C permite que o programador expresse sua preferência por registradores, na alocação de uma variável Registradores da CPU são de acesso muito mais rápido que o das palavras da RAM Registradores da CPU são de acesso muito mais rápido que o das palavras da RAM Assim, os programas poderão ficar mais rápidos Assim, os programas poderão ficar mais rápidos A declaração register int i; A declaração register int i; indica que a variável inteira i deve, se possível, ser alocada num registrador

61 Há limitação para o uso de registradores nos programas Há limitação para o uso de registradores nos programas Devido à sua sofisticada e cara tecnologia, eles são em número muito menor do que o das palavras da RAM Devido à sua sofisticada e cara tecnologia, eles são em número muito menor do que o das palavras da RAM Nem todas as variáveis de um grande programa poderão caber no conjunto de registradores de um computador Nem todas as variáveis de um grande programa poderão caber no conjunto de registradores de um computador Portanto o programador deve escolher as variáveis mais referenciadas para serem alocadas em registradores Portanto o programador deve escolher as variáveis mais referenciadas para serem alocadas em registradores Fortes candidatas para essa alocação são as variáveis usadas em controle de laços Fortes candidatas para essa alocação são as variáveis usadas em controle de laços Variáveis em registradores, tais como as automáticas, só permanecem alocadas durante a execução de seu bloco Variáveis em registradores, tais como as automáticas, só permanecem alocadas durante a execução de seu bloco

62 8.5.5 – Variáveis estáticas A declaração static int a; A declaração static int a; diz que a variável inteira i é estática Variáveis estáticas podem ser locais ou externas Variáveis estáticas podem ser locais ou externas Diferentes propriedades e utilidades têm as variáveis estáticas locais e externas Diferentes propriedades e utilidades têm as variáveis estáticas locais e externas Uma variável estática local tem seu valor conservado entre duas execuções consecutivas de seu bloco de declaração Uma variável estática local tem seu valor conservado entre duas execuções consecutivas de seu bloco de declaração Ao contrário, as variáveis automáticas perdem esse valor Ao contrário, as variáveis automáticas perdem esse valor

63 Exemplo: seja o programa: #include #include int i; void f () { static int a = 0; int b = 5; printf ("a = %3d; b = %3d;", a, b); b = i + 10; printf (" b = %3d;\n", b); a += 3; } void main () { for (i = 1; i <= 10; i++) f (); getch();} Resultado Variáveis estáticas locais são de uso privativo de seu bloco de declaração

64 Variáveis estáticas externas oferecem um importante serviço de privacidade, fundamental para a modularização de programas Variáveis estáticas externas oferecem um importante serviço de privacidade, fundamental para a modularização de programas Seu escopo de validade começa no ponto da declaração e vai somente até o final de seu arquivo Seu escopo de validade começa no ponto da declaração e vai somente até o final de seu arquivo Se o programa tiver outros arquivos, essa variável não é visível em suas funções Se o programa tiver outros arquivos, essa variável não é visível em suas funções Então, pode-se escrever um módulo com um conjunto de funções que tenham uso privativo de certas variáveis Então, pode-se escrever um módulo com um conjunto de funções que tenham uso privativo de certas variáveis Desse conjunto, uma função pode ser a líder e as outras podem ser suas auxiliares Desse conjunto, uma função pode ser a líder e as outras podem ser suas auxiliares

65 Capítulo VIII – Subprogramação 8.1 – Introdução 8.2 – Escopo de validade de declarações 8.3 – Parâmetros e passagem de argumentos 8.4 – Prototipação de subprogramas 8.5 – Classes de alocação 8.6 – Recursividade

66 8.6.1 – Definições matemáticas recursivas Recursividade é um expediente muito usado para se estabelecer certas definições matemáticas Recursividade é um expediente muito usado para se estabelecer certas definições matemáticas Uma entidade de uma certa classe é definida em função de entidades menores da mesma classe Uma entidade de uma certa classe é definida em função de entidades menores da mesma classe

67 Exemplo 1: seja S n a soma dos n primeiros inteiros positivos Exemplo 1: seja S n a soma dos n primeiros inteiros positivos Sn = Sn = Sn = Sn = Para n = 5: 1, para n = 1 n + S n-1, para n > 1 S 5 = 5 + S 4 = 5 + (4 + S 3 ) = 5 + (4 + (3 + S 2 )) = 5 + (4 + (3 + (2 + S 1 ))) = 5 + (4 + (3 + (2 + 1))) = 5 + (4 + (3 + 3)) = 5 + (4 + 6) = = 15

68 Exemplo 2: cálculo de fatoriais Exemplo 2: cálculo de fatoriais n! = n! = Para n = 5: -1, para n < 0 1, para 0 n 1 n * (n-1)!, para n > 1 5! = 5 * 4! = 5 * (4 * 3!) = 5 * (4 * (3 * 2!)) = 5 * (4 * (3 * (2 * 1!))) = 5 * (4 * (3 * (2 * 1))) = 5 * (4 * (3 * 2)) = 5 * (4 * 6) = 5 * 24 = 120

69 Exemplo 3: cálculo do mdc de números não-negativos Exemplo 3: cálculo do mdc de números não-negativos mdc (m, n) = mdc (m, n) = Para m = 48 e n = 64:, para m = 0 e n = 0 m, para m > 0 e n = 0 n, para m = 0 e n > 0 mdc (n, m%n), para m e n > 0 mdc (48, 64) = mdc (64, 48) = mdc (48, 16) = mdc (16, 0) = 16

70 8.6.2 – Subprogramas recursivos Subprograma recursivo: invoca a si próprio direta ou indiretamente Subprograma recursivo: invoca a si próprio direta ou indiretamente Recursividade direta: um subprograma invoca a si próprio em seus próprios comandos Recursividade direta: um subprograma invoca a si próprio em seus próprios comandos Recursividade indireta: um primeiro subprograma invoca outro, que invoca outro,..., que invoca outro, que invoca o primeiro Recursividade indireta: um primeiro subprograma invoca outro, que invoca outro,..., que invoca outro, que invoca o primeiro

71 #include #include int fat (int n) { int f; if (n < 0) f = -1; else if (n <= 1) f = 1; else f = n * fat(n-1); return f; } void main() { char c; int n; printf ("Calculo do fatorial de n"); printf ("Calculo do fatorial de n"); printf ("\n\n\tDigite n: "); scanf ("%d", &n); printf ("\n\n\tDigite n: "); scanf ("%d", &n); printf ("\n\tFat(%d) = %d", n, fat(n)); printf ("\n\tFat(%d) = %d", n, fat(n)); printf("\n\nDigite algo para encerrar: "); getch(); printf("\n\nDigite algo para encerrar: "); getch();} Exemplo 1: cálculo de fatoriais -1, para n < 0 n! =1, para 0 n 1 n * (n-1)!, para n > 1

72 #include #include int mdc (int m, int n) { int r; m = abs(m); n = abs(n); m = abs(m); n = abs(n); if (m==0 && n==0) r = -1; else if (m == 0) r = n; else if (n == 0) r = m; else r = mdc(n, m%n); return r; } void main() { char c; int m, n; printf ("Calculo do mdc de m e n"); printf ("Calculo do mdc de m e n"); printf ("\n\n\tDigite m e n: "); scanf ("%d%d", &m, &n); printf ("\n\n\tDigite m e n: "); scanf ("%d%d", &m, &n); printf ("\n\tmdc(%d, %d) = %d", m, n, mdc(m, n)); printf ("\n\tmdc(%d, %d) = %d", m, n, mdc(m, n)); printf("\n\nDigite algo para encerrar: "); getch(); printf("\n\nDigite algo para encerrar: "); getch();} Exemplo 2: cálculo de mdcs, p/ m = 0 e n = 0 mdc (m, n) = m, p/ m > 0 e n = 0 n, p/ m = 0 e n > 0 mdc (n, m%n), p/ m e n > 0

73 8.6.3 – Execução de subprogramas recursivos Quando um subprograma invoca a si mesmo, inicia-se uma nova execução (nova versão) desse subprograma Quando um subprograma invoca a si mesmo, inicia-se uma nova execução (nova versão) desse subprograma Porém a versão que faz a invocação continua ativa Porém a versão que faz a invocação continua ativa Em programas recursivos, pode haver várias versões ativas de um mesmo subprograma recursivo Em programas recursivos, pode haver várias versões ativas de um mesmo subprograma recursivo Cada qual com suas variáveis locais Cada qual com suas variáveis locais As variáveis de versões diferentes têm o mesmo nome mas são entidades distintas As variáveis de versões diferentes têm o mesmo nome mas são entidades distintas

74 #include #include int fat (int n) { int f; if (n < 0) f = -1; else if (n <= 1) f = 1; else f = n * fat(n-1); return f; } void main() { char c; int n; printf ("Calculo do fatorial de n"); printf ("Calculo do fatorial de n"); printf ("\n\n\tDigite n: "); scanf ("%d", &n); printf ("\n\n\tDigite n: "); scanf ("%d", &n); printf ("\n\tFat(%d) = %d", n, fat(n)); printf ("\n\tFat(%d) = %d", n, fat(n)); printf("\n\nDigite algo para encerrar: "); printf("\n\nDigite algo para encerrar: "); getch(); getch();} Exemplo: execução da função fat recursiva

75 #include #include int fat (int n) { int f; if (n < 0) f = -1; else if (n <= 1) f = 1; else f = n * fat(n-1); return f; } void main() { char c; int n; printf ("Calculo do fatorial de n"); printf ("Calculo do fatorial de n"); printf ("\n\n\tDigite n: "); scanf ("%d", &n); printf ("\n\n\tDigite n: "); scanf ("%d", &n); printf ("\n\tFat(%d) = %d", n, fat(n)); printf ("\n\tFat(%d) = %d", n, fat(n)); printf("\n\nDigite algo para encerrar: "); printf("\n\nDigite algo para encerrar: "); getch(); getch();} Valor digitado: 5 5 n

76 #include #include int fat (int n) { int f; if (n < 0) f = -1; else if (n <= 1) f = 1; else f = n * fat(n-1); return f; } void main() { char c; int n; printf ("Calculo do fatorial de n"); printf ("Calculo do fatorial de n"); printf ("\n\n\tDigite n: "); scanf ("%d", &n); printf ("\n\n\tDigite n: "); scanf ("%d", &n); printf ("\n\tFat(%d) = %d", n, fat(n)); printf ("\n\tFat(%d) = %d", n, fat(n)); printf("\n\nDigite algo para encerrar: "); printf("\n\nDigite algo para encerrar: "); getch(); getch();} Valor digitado: 5 5 n 5 n f fat – v1 f = 5*fat(4) 4 n f fat – v2 f = 4*fat(3) 3 n f fat – v3 f = 3*fat(2) 2 n f fat – v4 f = 2*fat(1) 1 n f fat – v5 f =

77 Observação: funções recursivas envolvendo vetores, matrizes e estruturas serão apresentadas no próximo capítulo

78 Exercícios 8.6: Exercícios 8.6: 1.Uma importante função teórica conhecida como função de Ackermann tem a seguinte formulação recursiva: Ackermann (m, n) = Escrever uma função inteira recursiva em C que tenha como parâmetros duas variáveis inteiras longas m e n e que calcule e retorne o valor de Ackermann (m, n), utilizando a definição acima. Tal função deve retornar -1 (menos 1) se o valor de m ou de n forem negativos


Carregar ppt "Capítulo VIII – Subprogramação 8.1 – Introdução 8.2 – Escopo de validade de declarações 8.3 – Parâmetros e passagem de argumentos 8.4 – Prototipação de."

Apresentações semelhantes


Anúncios Google