Funções
Funções são blocos de código reutilizáveis que realizam uma tarefa específica. Esses blocos de código têm nome através do qual os chamamos para execução.
Definição de uma função
A definição de uma função fornece o código real que a função executará. A estrutura geral de uma definição de função é a seguinte:
tipo_da_função nome_da_funcao(tipo_de_argumento1, tipo_de_argumento2, ...)
{
// Corpo da função
// Código para executar a tarefa desejada
}
Exemplo:
int soma(int a, int b)
{
int resultado = a + b;
return resultado;
}
De notar que o tipo da função define o tipo de dados que a função retorna.
Se uma função é do tipo double ela deve retornar um valor do tipo double.
Funções do tipo void
Uma função do tipo void é uma função que não retorna qualquer valor para o exterior.
Exemplo:
void ola()
{
printf("Olá, mundo!\n");
}
A instrução return
A instrução return serve para retornar um valor para o exterior da função. Ao mesmo tempo, ela termina a execução da função.
No caso das funções do tipo void, a instrução return não é obrigatória mas, se existir, não retorna qualquer valor terminando simplesmente a execução da função:
void mostraIdade(int idade){
if(idade < 10){
return; //termina a execução da função
}
printf("Tem %d anos de idade", idade);
}
Protótipo de uma função
Em C, geralmente é uma boa prática declarar um protótipo de função antes de usá-la. O protótipo fornece informações sobre a função, permitindo que o compilador verifique se está a usar a função corretamente.
O protótipo de uma função é basicamente o nome da função o seu tipo, os seus parâmetros e respetivos tipos:
int somar(int nr1, int nr2);
O protótipo de uma função é geralmente declarado logo a seguir às instruções para o pré-processador.
Parâmetros de uma função
Ao chamarmos uma função podemos-lhe passar valores (argumentos) que a função irá usar internamente.
Os parâmetros são definidos a seguir ao nome da função. Devemos indicar o tipo de cada parâmetro e o seu nome. Os parâmetros são variáveis para as quais passamos valores quando chamamos a função.
Exemplo:
// Função que recebe dois inteiros e os imprime
void imprimirValores(int a, int b)
{
printf("Dentro da função: a = %d, b = %d\n", a, b);
}
int main()
{
int x = 5;
int y = 10;
printf("Antes da função: x = %d, y = %d\n", x, y);
imprimirValores(x, y);
printf("Depois da função: x = %d, y = %d\n", x, y);
return 0;
}
Neste exemplo, imprimirValores recebe dois inteiros por valor e imprime seus valores dentro da função. Qualquer alteração feita em a e b dentro da função não afetará x e y fora da função.
Os dados foram passados para a função imprimirVaores por valor, ou seja, os valores nas variáveis x e y, foram copiados para as variáveis de parâmetros a e b.
Passagem de parâmetros por referência
Ao contrário da passagem por valor que vimos acima, na passagem por referência passamos os endereços das variáveis cujos dados queremos passar para a função:
Na função, as variáveis dos parâmetros são declaradas como ponteiros:
// Função que modifica o valor através de um ponteiro
void modificarValor(int *ptr)
{
*ptr = 100;
}
int main()
{
int x = 5;
printf("Antes da função: x = %d\n", x);
modificarValor(&x);
printf("Depois da função: x = %d\n", x);
return 0;
}
Neste exemplo, a função modificarValor recebe um ponteiro para um inteiro e altera o valor apontado pelo ponteiro. Assim, a função pode modificar o valor de x fora da função.
Passagem de arrays para uma função
Podemos passar arrays para funções em C. No entanto, os arrays são tratados como ponteiros para o primeiro elemento do array dentro da função. Quando passamos um array para uma função temos de passar também o seu tamanho:
// Função que calcula a soma dos elementos de um array
int somaArray(int arr[], int tamanho)
{
int soma = 0;
for (int i = 0; i < tamanho; i++)
{
soma += arr[i];
}
return soma;
}
int main()
{
int numeros[] = {1, 2, 3, 4, 5};
int tamanho = 5;
//chamamos a função passando a função e o seu tamanho:
int resultado = somaArray(numeros, tamanho);
printf("A soma dos elementos do array é: %d\n", resultado);
return 0;
}
Na instrução
int resultado = somaArray(numeros, tamanho);
quando passamos o array pelo seu nome, estamos a passar de facto o endereço de memória do primeiro elemento do array.
Passagem de strings para uma função
Em C, as strings são tratadas como arrays de caracteres. Portanto, podemos passar strings para funções como um array de caracteres:
// Função que imprime uma string
void imprimirString(char str[])
{
printf("A string passada é: %s\n", str);
}
int main()
{
char str[] = "Olá, Mundo!";
imprimirString(str);
return 0;
}
De notar que ao passarmos a string para a função não necessitamos de passar o seu tamanho dado que as strings em C terminam com o caractere null (\0).
Chamada de uma função
Básicamente, chamamos uma função evocando o seu nome e passando valores, caso a função tenha parâmetros.
Se a função tiver um tipo que não seja void, guardamos o valor retornado pela função, numa variável:
int somaValores(int nr1, int nr2, int nr3){
return nr1 + nr2 + nr3;
}
int main()
{
int resultado;
//chama a função e guarda o resultado retornado pela função na variável resultado:
resultado = somaValores(7, 3, 9);
}
Se a função chamada fôr do tipo void, chamamos simplesmente a função pelo nome, passando-lhe valores caso a função tenha parâmetros:
void saudar(char msg[] ){
puts(msg);
}
int main()
{
//chama a função evocando o seu nome:
saudar("Bem vindos a linguagem C");
}
Funções recursivas
Uma função recursiva é uma função que se chama a si mesma.
As funções recursivas geralmente consistem em duas partes:
- Caso Base: É a condição em que a função para de se chamar a si mesma e retorna um valor direto. É importante definir um caso base para evitar que a recursão continue indefinidamente, o que levaria a um estouro da pilha do programa (stack overflow).
- Caso Recursivo: É a parte da função que se chama a si mesma com parâmetros diferentes. O objetivo é reduzir o problema original em subproblemas menores até que o caso base seja alcançado.
Exemplo:
int fatorial(int n)
{
if (n <= 1)
return 1; //caso base
else
return n * fatorial(n - 1); //caso recursivo
}
Neste exemplo, a função fatorial chama-se a si própria com um valor menor até que o caso base seja atingido (quando n é igual a 0 ou 1).
