| <<< Voltar | Avançar >>> |
8. Funções
8.1 Forma geral de uma função
TIPO NOME(PARÂMETROS)
{
CORPO DA FUNÇÃO
}
|
Onde:
- TIPO é o tipo de valor retornado pela função. Se nada for especificado o compilador considera que será retornado um valor inteiro.
- NOME é o nome da função
- PARÂMETROS é a lista das variáveis que recebem os argumentos quando a função é chamada. Deve incluir o tipo e nome de cada variável. Sua sintaxe é:(tipo variável1, tipo variável2, ......, tipo variáveln)
- CORPO é onde estão as instruções da função
Exemplo:
int soma(int a,int b)
{
int resultado;
resultado = a + b;
return(resultado);
}
|
8.2 Variáveis em funções
As variáveis criadas numa função são locais, assim serão destruídas após o término da função.
Caso você queira manter o valor de uma variável entre as chamadas a uma função você deve declarar esta variável como static. Exemplo:
/* Mantendo o valor de uma variável entre as
* chamadas de uma função */
#include <stdio.h>
int soma_1(int a);
int main()
{
int nr = 1;
printf("Chamando a função a primeira vez: valor + 1 = %d\n",
soma_1(nr));
printf("Chamando a função pela segunda vez: : valor + 1 = %d\n",
soma_1(nr));
printf("Chamando a função pela terceira vez: : valor + 1 = %d\n",
soma_1(nr));
return(0);
}
int soma_1(int a)
{
static int valor = 1;
printf("valor = %d\n",valor);
valor = valor + a;
return(valor);
}
|
Caso uma variável local a função tenha o mesmo nome de uma variável global, a variável local será usada e não a global. Exemplo:
/* Entre variáveis locais e globais com o mesmo nome
* dentro de uma função, a variável local é escolhida */
#include <stdio.h>
int a = 1; /* variável global */
void exibe(void)
{
int a = 10; /* variável local a função exibe() */
printf("a dentro da função = %d\n",a);
}
int main()
{
printf("\n");
printf("a dentro de main = %d\n",a);
exibe();
printf("\n");
return(0);
}
|
BIZÚ: Evite variáveis globais.
8.3 Argumentos e parâmetros
Argumentos são os valores usados para chamar a função e parâmetros são as variáveis, declaradas na definição da função, que recebem estes argumentos. Observe o exemplo abaixo:
/* Argumentos e parâmetros */
#include <stdio.h>
int soma(int a, int b) /* "a" e "b" são os parâmetros da função "soma" */
{
int resultado;
resultado = a + b;
return(resultado);
}
int main()
{
printf("A soma entre 5 e 2 é %d\n",soma(5,2));
/* No comando printf acima a função "soma" é chamada
* com os argumentos 5 e 2 */
return(0);
}
|
Os tipos dos argumentos devem ser compatíveis com os tipos dos parâmetros.
Você encontrará também referência aos parâmetros formais e paramêros reais. Os parâmetros formais são os parâmetros propriamente ditos, enquanto que os parâmtros reais são os argumentos.
8.4 Parâmetros
Existem duas formas de declaração de parâmetros em funções: a forma clássica e a forma moderna.
A forma clássica tem a seguinte sintaxe:
TIPO NOME(PARÂMETRO1, PARÂMETRO2, ... , PARÂMETROn)
TIPO DO PARÂMETRO1;
TIPO DO PARÂMETRO2;
...
...
TIPO DO PARÂMETROn;
{
CORPO DA FUNÇÃO
}
|
Já a forma moderna tem a seguinte sintaxe:
TIPO NOME(TIPO PARÂMETRO1, TIPO PARÂMETRO2, ... , TIPO PARÂMETROn)
{
CORPO DA FUNÇÃO
}
|
Abaixo segue um exemplo de função com os dois tipos de declaração de parâmetros.
/* Com declaração clássica */
int soma(a, b)
int a;
int b;
{
int resultado;
resultado = a + b;
return(resultado);
}
/* Com declaração moderna */
int soma(int a, int b)
{
int resultado;
resultado = a + b;
return(resultado);
}
|
Atualmente utiliza-se a forma moderna, porém, em programas mais antigos você encontrará a forma clássica.
8.5 Chamada por valor e chamada por referência
A chamada por valor é a passagem normal do valor dos argumentos para a função. Utilizando esta chamada os valores dos argumentos passados não são modificados. Na realidade é passada uma cópia dos valores para a função.
Na chamada por referência são passados os endereços de memória onde estão os argumentos. Neste tipo de chamada os valores podem ser modificados.
Abaixo segue um exemplo de uma chamada por valor:
/* Testando a chamada por valor */
#include <stdio.h>
/* Função com chamada por valor */
int valor(int a, int b)
{
a = a + 3; /* Modificando o primeiro argumento */
b = b + 2; /* Modificando o segundo argumento */
printf("Valores modificados dentro da função:\n");
printf("nr1 = %d\n",a);
printf("nr2 = %d\n",b);
}
int main()
{
int nr1 = 2, nr2 = 3, total;
printf("\n");
printf("Chamada por valor\n");
printf("=================\n");
printf("Valores iniciais de nr1 e nr2\n");
printf("nr1 = %d\n",nr1);
printf("nr2 = %d\n",nr2);
printf("\n\nChamando a função\n");
valor(nr1,nr2); /* Neste tipo de chamada são passados os argumentos
* normalmente. Na verdade a função recebe uma cópia
* destes argumentos */
printf("\n\nValores após a chamada da função\n");
printf("nr1 = %d\n",nr1);
printf("nr2 = %d\n",nr2);
return(0);
}
|
Agora o mesmo exemplo com a chamada por referência:
/* Testando a chamada por referência */
#include <stdio.h>
/* Função com chamada por referência */
int valor(int *a, int *b)
{
*a = *a + 3; /* Modificando o primeiro argumento */
*b = *b + 2; /* Modificando o segundo argumento */
printf("Valores modificados dentro da função:\n");
printf("nr1 = %d\n",*a);
printf("nr2 = %d\n",*b);
}
int main()
{
int nr1 = 2, nr2 = 3, total;
printf("\n");
printf("Chamada por referência\n");
printf("======================\n");
printf("Valores iniciais de nr1 e nr2\n");
printf("nr1 = %d\n",nr1);
printf("nr2 = %d\n",nr2);
valor(&nr1,&nr2); /* Neste tipo de chamada é passado o endereço do
* argumento. Neste tipo de chamada os valores
* podem ser modificados */
printf("\n\nValores após a chamada da função\n");
printf("nr1 = %d\n",nr1);
printf("nr2 = %d\n",nr2);
return(0);
}
|
OBSERVAÇÃO: As strings e matrizes sempre são chamadas por referência. Quando C passa uma matriz ou string para uma função é passado o endereço inicial da matriz ou função.
8.6 Argumentos da linha de comando
Caso queira, você pode passar argumentos diretamente para a função main(). Como main () é a primeira função a ser chamada quando você chama o programa os argumentos para ela são passados junto com o comando que chama o programa, geralmente seu nome. Estes argumentos são conhecidos como argumentos da linha de comando. Observe o exemplo abaixo:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Olá %s.\n",argv[1]);
return(0);
}
|
Os argumentos da linha de comando são argc e argv. argc armazena o número de argumentos passados para o programa, inclusive o nome do programa. argv é uma matriz de strings e armazena o nome do programa e os argumentos passados. argv[0] armazena o nome do programa, argv[1] armazena o primeiro argumento passado para o programa, argv[2] armazena o segundo argumento passado para o programa, e assim por diante. Os argumentos são seprarados por um espaço.
8.7 O comando return
O comando return é usado para encerrar a função e retornar um valor para a função chamadora. Exemplo:
#include <stdio.h>
float total(float preco, float taxa_juros)
{
float preco_final, juros;
juros = preco * (taxa_juros / 100);
preco_final = preco + juros;
return(preco_final);
}
int main()
{
float preco, taxa_juros, preco_final;
printf("\n");
printf("Preço na etiqueta :");
scanf("%f",&preco);
printf("\n");
printf("Taxa de juros :");
scanf("%f",&taxa_juros);
preco_final = total(preco, taxa_juros);
printf("\n");
printf("Total a pagar : %4.2f\n\n",preco_final);
return(0);
}
|
O valor retornado por return deve ser compatível com o tipo da função, o qual é definido quando da sua declaração.
float total(float preco, float taxa_juros) |
No exemplo, a função total retorna um valor float. Isto é determinado pela colocação do tipo float antes do nome da função, como mostrado acima.
Se uma função não retornar nenhum valor ela é do tipo void. Exemplo:
#include <stdio.h>
void nao_retorna()
{
printf("Esta função não retorna nada.\n");
}
int main()
{
nao_retorna();
return(0);
}
|
De acordo com o padrão ANSI, a função main devolve um inteiro para o processo chamador, que geralmente é o sistema operacional. Isto é equivalente a chamar exit com o mesmo valor. Alguns compiladores ainda aceitam que main seja declarada como void caso não retorne nenhum valor.
8.8 Protótipo de função
A chamada a uma função deve vir, a princípio, após sua definição para o compilador conhecer os tipos de parâmetros e o tipo de retorno da função. Porém, você pode chamar a função antes da definição desta. Para isso declare apenas um protótipo da função, o qual tem apenas o valor de retorno e os parâmetros da função. Observe o exemplo abaixo:
#include <stdio.h>
int soma(int a, int b); /* protótipo da função */
int main()
{
int nr1, nr2;
printf("Entre com o primeiro número :");
scanf("%d",&nr1);
printf("Entre com o segundo número :");
scanf("%d",&nr2);
printf("\n%d + %d = %d\n\n",nr1,nr2,soma(nr1,nr2));
return(0);
}
int soma(int a, int b) /* função propriamente dita */
{
int resultado;
resultado = a + b;
return(resultado);
}
|
8.9 Recursão
Recursão é o ato de uma função chamar ela mesma. Uma função que chama a ela mesma é chamada função recursiva.
O exemplo padrão de função recursiva é uma função que calcula o fatorial de um número. O fatorial de um número é igual ao produto dos números inteiros de 1 até o número.
fatorial de 5 = 5 * 4 * 3 * 2 * 1 |
Se você observar com cuidado verá que:
fatorial de 5 = 5 * fatorial de 4 fatorial de 4 = 4 * fatorial de 3 fatorial de 3 = 3 * fatorial de 2 fatorial de 2 = 2 * fatorial de 1 |
Ou seja
fatorial de um número = número * (fatorial de número - 1) |
Desta conclusão podemos escrever nosso exemplo de função recursiva:
/* Exemplo de função recursiva */
#include <stdio.h>
int fatorial(nr)
{
int resposta;
if(nr == 1)
return(1);
resposta = nr * fatorial(nr-1);
return(resposta);
}
int main()
{
int a;
printf("\nEntre com um valor inteiro :");
scanf("%d",&a);
printf("O fatorial de %d é %d\n\n",a,fatorial(a));
return(0);
}
|
A recursão sempre deve ser evitada basicamente por dois fatores. Primeiro que uma função recursiva é difícil de compreender. Segundo que as funções recursivas são mais lentas que suas correspondentes não recursivas.
Normalmente uma função recursiva também pode ser escrita com laços de repetição tipo for ou while de modo a remover a recursão.
| <<< Voltar | Avançar >>> |