Você está na página 1de 4

5.

Funções e recursividade
As funções dividem grandes tarefas de computação em tarefas menores. A criação de
funções evita a repetição de código, de modo que um procedimento que é repetido deve
ser transformado numa função que, então, será chamada diversas vezes. Um programa
bem estruturado deve ser pensado em termos de funções.
A definição de uma função na linguagem C fornece quatro informações importantes ao
compilador: 1. quem pode chamá-la; 2. o tipo do valor que a função devolve; 3. seu
identificador; 4. seus parâmetros de entrada.
Uma função é composta por:
• Uma interface, que faz a comunicação entre a função e o meio exterior; a interface
é definida pela primeira linha da função, onde especificamos o tipo do valor
devolvido da função, seu identificador e a lista de parâmetros de entrada.
• Um corpo, que realiza o processamento sobre os valores armazenados nos
parâmetros de entrada, o corpo de uma função é composto pela declaração de
variáveis locais da função e sua lista de comandos.
De forma geral de uma definição de uma função é:
tipo identificador(parâmetros)
{
declaração de variáveis sentenças
}
A primeira linha apresentada é a interface da função e as linhas seguintes, envolvidas por
chaves, compõem o corpo da função. A interface da função inicia com um tipo , que
especifica o tipo do valor a ser devolvido pela função. Funções não podem devolver
variáveis compostas homogêneas, mas não há qualquer outra restrição quanto ao tipo de
valor a ser devolvido. No entanto, especificar que o valor devolvido é do tipo void indica
que a função não devolve um valor. Depois, a interface contém o identificador da função,
que é seu nome e que a identifica e diferencia de outras funções. E, finalmente, a interface
contém os parâmetros , que armazenam valores a serem recebidos como entrada pela
função, envolvidos por parênteses. A lista de parâmetros é composta por tipos e
identificadores de variáveis, separados por vírgulas. Um tipo deve ser especificado para
cada parâmetro, mesmo que vários parâmetros sejam do mesmo tipo.

Ex:
double media(double a, double b)
{
return (a + b) / 2;
}
A palavra reservada double na primeira linha é o tipo do valor devolvido da função media,
que é o tipo do valor devolvido pela função cada vez que ela é chamada. Os
identificadores a e b, chamados de parâmetros da função, representam os dois números
que serão fornecidos quando a função media é chamada. Assim como uma variável, um
parâmetro deve ter um tipo. No exemplo, ambos os parâmetros a e b são do tipo double .
Um parâmetro de uma função é essencialmente uma variável cujo valor inicial é fornecido
quando da sua chamada.
Toda função tem um trecho executável, chamado de corpo, envolvido por abre e fecha
chaves. O corpo de função media consiste de uma única sentença return . A execução
dessa sentença faz com que a função regresse para o ponto de onde foi chamada. O valor
(a + b) / 2 será devolvido pela função.
Para chamar uma função, escrevemos o nome da função seguido por uma lista de
argumentos. Por exemplo, media(x, y) é uma chamada da função media. O efeito da
chamada media(x, y) é primeiro copiar os valores de x e y nos parâmetros a e b e, em
seguida, executar o corpo de media.
Se a função não tem parâmetros, a palavra reservada void deve ocorrer entre os
parênteses.
A declaração de variáveis de uma função deve vir primeiro, antes de qualquer sentença
do corpo da função. As variáveis declaradas no corpo de uma função pertencem
exclusivamente àquela função e não podem ser examinadas ou modificadas por outras
funções. cada vez que a função é executada, as variáveis locais são criadas, e, quando a
execução da função termina, estas variáveis deixam de existir.
Uma chamada de função consiste de um identificador da função seguido por uma lista de
argumentos entre parênteses. Ex:
media(x, y)
imprimeContador(i)
imprimeMsg()
Uma chamada de uma função com valor devolvido void é sempre seguida por um ; para
torná-la uma sentença. Ex:
imprimeContador(i);
imprimeMsg();
A declaração de uma função também é conhecida como protótipo da função. Os
protótipos servem para dar ao compilador informações sobre as funções. Isso para que
você possa chamar funções antes que o compilador tenha a definição (completa) das
funções. O protótipo de uma função é idêntico ao cabeçalho da função, mas o nome dos
argumentos podem ser omitidos e ele é terminado com uma vírgula.
Protótipos declaram uma função ao invés de defini-las. O formato dos protótipos é:
tipo-de-retorno nome-da-função(lista-dos-tipos-dos-argumentos);
A principal vantagem de definir protótipos é que erros de chamada de funções (como
chamar uma função com o número incorreto de argumentos, ou com argumentos de tipo
errado) são detectados pelo compilador.
Chamamos de recursividade ou recursão quando uma função chama a si mesma. Em uma
função recursiva, a cada chamada é criada na memória uma nova ocorrência da função
com comandos e variáveis “isolados” das ocorrências anteriores. A função é executada
até que todas as ocorrências tenham sido resolvidas.
A recursão é uma técnica que define um problema em termos de uma ou mais versões
menores deste mesmo problema. Esta ferramenta pode ser utilizada sempre que for
possível expressar a solução de um problema em função do próprio problema.
Toda recursividade é composta por um caso base e pelas chamadas recursivas. O caso
base: é o caso mais simples. É usada uma condição em que se resolve o problema com
facilidade. As chamadas recursivas: procuram simplificar o problema de tal forma que
convergem para o caso base.
Em procedimentos recursivos pode ocorrer um problema de terminação do programa,
como um “looping interminável ou infinito”. para determinar a terminação das repetições,
deve-se:
• Definir uma função que implica em uma condição de terminação (solução trivial),
• Provar que a função decresce a cada passo de repetição, permitindo que,
eventualmente, esta solução trivial seja atingida.
Uma estrutura recursiva utiliza a seguinte estratégia:
se a entrada do problema é pequena então
resolva-a diretamente;
senão,
reduza-a a uma entrada menor do mesmo problema, aplique este método à
entrada menor e volte à entrada original.
Um exemplo clássico de uma função recursiva é aquela que computa o fatorial de um
número inteiro n > 0. A idéia da solução através de uma recursiva é baseada na fórmula
mostrada a seguir:
n! = 1 , se n <= 1 ; n × (n − 1)! , caso contrário.

int fat(int n)
{
int result;
if (n <= 1)
result = 1;
else
result = n * fat(n-1);
return result;
}
Um programa recursivo torna a escrita do código mais simples e elegante, tornando-o
fácil de entender e de manter, exibindo com maior clareza o processo utilizado. Por outro
lado, um programa recursivo exige mais espaço de memória e é, na grande maioria dos
casos, mais lento do que a versão iterativa.

Você também pode gostar