INF1005: PROGRAMAÇÃO I Capítulo 12 Ivan Mathias Filho ivan@inf.puc-rio.br 1 Funções Matemáticas Função é uma relação de um ou vários valores de argumentos de entrada em um ÚNICO resultado de saída. O conjunto de todos os valores de entrada de uma função é chamado de DOMÍNIO da função. O conjunto de todos os resultados é chamado de IMAGEM da função. A IMAGEM é um subconjunto de um conjunto de resultados possíveis, chamado de CONTRADOMÍNIO. 2 1
Funções e Procedimentos (1) Uma função matemática lembra uma máquina que recebe valores para os seus argumentos de entrada, processa-os e retorna um valor como saída (Figuras A e B). 3 Funções e Procedimentos (2) Em computação nós estendemos este conceito permitindo que estas máquinas produzam efeitos colaterais (como exibir uma mensagem no monitor) (Figura C). Admite-se, também, que a máquina não retorne valor algum (Figura D). 4 2
Funções e Procedimentos (3) Neste caso, podemos dizer que as máquinas deixam de ser equivalentes a funções matemáticas (i.e. deixam de ser FUNCIONAIS) e passam a ser PROCEDIMENTAIS, no sentido de que seguem um procedimento, claro, sequencial e com possíveis efeitos colaterais que afetam o ambiente. 5 Uso de Funções em Expressões (1) Sejam as seguintes funções matemáticas: : 2 2 :, 2 3 4 6 3
Uso de Funções em Expressões (2) Garfield, você poderia resolver a equação w = f(2) + g(1,3)? Como posso resolvê-la se não sei quais são os valores de f(2) e de g(1,3)? 7 Uso de Funções em Expressões (3) Espera aí: Scooby, qual Ótimo! é o Agora valor de só falta calcular f(2)? g(1,3). w=10+g(1,3) Está na mão: 2*(2) 2 + 2 = 10!!! 8 4
Uso de Funções em Expressões (4) Snoopy, qual é o valor de g(1,3)? Feito!!!! w=10+15 w=25 Toma aí: 2(1)+ 3(3)+4 = 15!!! 9 Organização de Código (1) Um programa de computador representa a implementação de uma solução de um determinado problema. O processo de desenvolvimento de um programa envolve diversas etapas: Entender o problema Fazer uma análise do problema tentando identificar possíveis soluções Desenvolver o projeto do software em si Por se tratar de um processo dinâmico, estamos constantemente revendo códigos já escritos, seja para corrigir eventuais erros encontrados, seja para usar como modelo para resolver um outro problema. 10 5
Organização de Código (2) Por isso é fundamental que nosso programa seja escrito de forma organizada, a fim de facilitar a alteração, a reutilização e a adaptação do código, durante o processo de desenvolvimento ou no futuro. A linguagem C fornece uma ferramenta que permite atingir bons resultados em relação aos requisitos acima. Esta ferramenta é chamada de função. Uma função é uma porção de código dentro de um programa maior que executa uma tarefa específica e relativamente independente do código restante. 11 Função (1) O uso de funções permite que trechos de código possam ser executados a partir de outros trechos de código, sem necessidade de replicação do código em questão. Esta é uma importante ferramenta, pois permite estender as operações nativas disponibilizadas pela linguagem. Por exemplo, a linguagem C oferece operadores nativos (embutidos) para somar, subtrair ou dividir inteiros. Operações trigonométricas, entretanto, não são implementadas nativamente, mas disponibilizadas através de uma biblioteca de funções matemáticas. 12 6
Função (2) Um programa C é dividido em pequenas funções: Bons programas são compostos por diversas pequenas funções. Como o próprio nome diz, uma função representa uma funcionalidade. A vantagem de se ter o código organizado em funções é que o ele fica mais fácil de entender, de alterar, de atualizar e de reusar. Toda função em C é definida da seguinte maneira: <tipo_retorno> <nome_função> (<lista_parâmetros>) { <bloco_comandos> Um programa C não pode ter duas funções com o mesmo nome. 13 Função (3) Um programa C não pode ter duas funções com o mesmo nome. <tipo_retorno> <nome_função> (<lista_parâmetros>) { <bloco_comandos> Se uma função não tem retorno colocamos void. Consiste no bloco de comandos que compõem a função. O valor retornado por uma função pertence ao domínio de um dos tipos primitivos vistos: int, float, double ou char. Se uma função não tem uma lista de parâmetros colocamos void. 14 7
Função (4) Uma grande vantagem de dividir o programa é aumentar seu potencial de reuso. #include <stdio.h> Podemos usar essa função em qualquer outro programa que precise de uma conversão desse tipo. float celsius_fahrenheit(float tc) { float tf; /* 6 */ tf = 1.8 * tc + 32; /* 7 */ return tf; /* 8 */ int main(void) { float cels; /* 1 */ float fahr; /* 2 */ printf( Entre com temperatura em Celsius: ); /* 3 */ scanf( %f, &cels); /* 4 */ fahr = celsius_fahrenheit(cels); /* 5 */ NO CÓDIGO AS FUNÇÕES DEVEM SER ESCRITAS ANTES DE SEREM CHAMADAS (exceção se usar.h) printf( Temperatura em Fahrenheit: ); /* 9 */ printf( %f, fahr); /* 10 */ return 0; /* 11 */ 15 Parâmetros e Valor de Retorno (1) Uma função deve ter uma INTERFACE bem definida, tanto do ponto de vista semântico quanto do ponto de vista sintático; SEMÂNTICO: quando projetamos uma função, identificamos sua funcionalidade (principalmente através do nome) e com isso definimos os dados de entrada necessários e o resultado (saída) produzido pela função. SINTÁTICO: os tipos dos dados de entrada e da saída são especificados no cabeçalho da função. 16 8
Parâmetros e Valor de Retorno (2) Analisando algumas funções: float celsius_fahrenheit(float tc) Funções que recebem mais de um parâmetro volume do cilindro: π x r 2 x h #define PI 3.14159 float volume_cilindro(float r,float h) { float v; v=pi*r*r*h; return v; 17 Parâmetros e Valor de Retorno (3) int main(void) { float raio, altura, volume; printf( Entre com o valor do raio: ); scanf( %f, &raio); printf( Entre com o valor da altura: ); scanf( %f, &altura); volume = volume_cilindro(raio, altura); printf( Volume do cilindro = ); printf( %f, volume); return 0; 18 9
Parâmetros e Valor de Retorno (4) Uma chamada de uma função pode aparecer dentro de uma expressão maior. Por exemplo, se quiséssemos calcular a metade do volume do cilindro: volume = volume_cilindro(raio,altura) / 2.0; Pode ser utilizada uma expressão válida na passagem de parâmetros: volume = volume_cilindro(raio,2.0*altura); 19 Escopo de Uma Variável (5) Ao encontrar a declaração de uma variável no corpo de uma função o sistema reserva espaço de memória para acomodá-la. Esse espaço de memória permanece alocado durante o tempo de vida da variável. Variável Local: Variável declarada dentro da função. Só é visível dentro da função em que está declarada. Assim que a função retorna o espaço de memória reservado para tal é liberado e devolvido ao sistema. Áreas de memória devolvidas ao sistema não podem mais ser acessadas. As variáveis locais são também chamadas de variáveis automáticas. 20 10
Escopo de Variáveis (1) Dentro de uma função não se tem acesso a variáveis locais definidas em outras funções. Os parâmetros de uma função também são variáveis automáticas e com o mesmo escopo das demais variáveis declaradas na função. Uma função pode ser chamada diversas vezes. Para cada execução da função, o espaço de memória alocado para as variáveis locais é automaticamente reservado e liberado ao final da execução. O valor de uma variável não é preservado entre chamadas consecutivas de uma função. 21 Escopo de Variáveis (2) #define PI 3.14159 float volume_cilindro(float raio,float altura) { float volume; volume=pi*raio*raio*altura; return volume; Os nomes das variáveis locais são iguais, mas elas ocupam áreas de memória diferentes. int main(void) { float raio, altura, volume; printf( Entre com o raio e a altura: ); scanf( %f%f, &raio, &altura); volume = volume_cilindro(raio, altura); printf( Volume do cilindro = ); printf( %f, volume); return 0; 22 11
Escopo de Variáveis (3) Não abordaremos nesse curso: Variável Global: Declarada fora das funções. Tempo de vida coincidente com o tempo de execução do programa. Visível por todas as funções subsequentes à sua declaração. Variável Estática: Tempo de vida coincidente com o tempo de execução do programa. Preserva o valor da variável entre chamadas consecutivas de uma função. Só é visível dentro da função que a declara. 23 Modelo de Execução de Pilha (1) A alocação das áreas de memória dos parâmetros e das variáveis locais segue um modelo de pilha. Isto é, as áreas de memória são alocadas no topo da pilha e removidas do topo da mesma. Logo, quando uma declaração de variável é encontrada, o espaço de memória no topo da pilha de execução é associado à variável. Quando o ciclo de vida da variável se extingue, o espaço correspondente do topo da pilha é liberado e devolvido ao sistema. 24 12
Modelo de Execução de Pilha (2) #include <stdio.h> #define PI 3.14159 float volume_cilindro(float r, float h) { float v; v = PI * r * r * h; return v; int main(void) { float raio, altura, volume; printf( Entre com o valor do raio: ); scanf( %f, &raio); printf( Entre com o valor da altura: ); scanf( %f, &altura); volume = volume_cilindro(raio, altura); printf( Volume do cilindro = ); printf( %f, volume); return 0; Início e declaração de 3 variáveis já alocando (reservando) o espaço de memória na pilha de execução. Como nenhuma variável foi inicializada, elas estão com lixo 25 Modelo de Execução de Pilha (3) #include <stdio.h> #define PI 3.14159 float volume_cilindro(float r, float h) { float v; v = PI * r * r * h; return v; int main(void) { float raio, altura, volume; printf( Entre com o valor do raio: ); scanf( %f, &raio); printf( Entre com o valor da altura: ); scanf( %f, &altura); volume = volume_cilindro(raio, altura); printf( Volume do cilindro = ); printf( %f, volume); Valores fornecidos pelo usuário, capturados e armazenados na posição correspondente. return 0; 26 13
Modelo de Execução de Pilha (4) #include <stdio.h> #define PI 3.14159 float volume_cilindro(float r, float h) { float v; v = PI * r * r * h; return v; int main(void) { float raio, altura, volume; printf( Entre com o valor do raio: ); scanf( %f, &raio); printf( Entre com o valor da altura: ); scanf( %f, &altura); volume = volume_cilindro(raio, altura); printf( Volume do cilindro = ); printf( %f, volume); A chamada da função representa uma transferência do fluxo de execução para a função. Os parâmetros da função são alocados na pilha e seus valores são inicializados com os valores passados na chamada da função. return 0; 27 Modelo de Execução de Pilha (5) No momento em que o controle da execução é transferido para a função auxiliar, não se tem mais acesso às variáveis declaradas dentro da função main, apesar delas ainda estarem alocadas na base da pilha. Lembre-se de que a função main ainda não terminou; ela apenas teve a sua execução suspensa. 28 14
Modelo de Execução de Pilha (6) #include <stdio.h> #define PI 3.14159 float volume_cilindro(float r, float h) { float v; v = PI * r * r * h; return v; int main(void) { float raio, altura, volume; printf( Entre com o valor do raio: ); scanf( %f, &raio); printf( Entre com o valor da altura: ); scanf( %f, &altura); volume = volume_cilindro(raio, altura); Na função auxiliar, uma nova variável é declarada (com valor indefinido). printf( Volume do cilindro = ); printf( %f, volume); return 0; 29 Modelo de Execução de Pilha (7) #include <stdio.h> #define PI 3.14159 float volume_cilindro(float r, float h) { float v; v = PI * r * r * h; return v; int main(void) {... Neste momento, os parâmetros e variáveis locais são desempilhados e deixam de existir. Seu valor é computado e atribuído à variável local. Este valor é retornado pela função. Neste momento a função auxiliar termina sua execução e devolve o controle para a main. 30 15
Modelo de Execução de Pilha (8) #include <stdio.h> #define PI 3.14159 float volume_cilindro(float r, float h) { float v; v = PI * r * r * h; return v; int main(void) { float raio, altura, volume; printf( Entre com o valor do raio: ); scanf( %f, &raio); printf( Entre com o valor da altura: ); scanf( %f, &altura); volume = volume_cilindro(raio, altura); printf( Volume do cilindro = ); printf( %f, volume); return 0; No retorno do controle para a main, o valor retornado pela função é atribuído à variável volume. SEMPRE: Ao término de cada função, as variáveis locais correspondentes são desempilhadas e o controle volta para a função que a chamou. 31 16