Funções — Básico

Funções são como receitas na cozinha — dê os ingredientes (parâmetros), elas seguem os passos para processá-los e servem um prato (valor de retorno). Encapsular lógica repetida em funções mantém o código limpo e eficiente.

Definição de função

Uma definição de função consiste de quatro partes: tipo de retorno, nome da função, lista de parâmetros e corpo da função.

C
int add(int a, int b) {
    return a + b;
}

Se não há parâmetros, escreva void na lista de parâmetros:

C
int get_value(void) {
    return 42;
}

Chamada de função

Para chamar uma função, coloque parênteses após o nome da função e passe os argumentos:

C
int result = add(3, 5);
printf("%d\n", result);

Ao ser chamada, o programa salta para o corpo da função, executa-o e retorna ao ponto da chamada ao encontrar return ou chegar ao fim da função.

Funções podem ser aninhadas — o valor de retorno de uma função pode servir como argumento para outra:

C
int x = add(add(1, 2), add(3, 4));

Isso equivale a add(3, 7), resultando em 10.

Parâmetros e valores de retorno

Parâmetros vs Argumentos

As variáveis nos parênteses da definição de função são chamadas parâmetros (parâmetros formais). Os valores passados na chamada são chamados argumentos (parâmetros reais).

C
int square(int n) {
    return n * n;
}

int main(void) {
    int x = 5;
    int y = square(x);
    return 0;
}

n é um parâmetro, x é um argumento. Parâmetros são variáveis locais dentro da função; o valor do argumento é copiado para o parâmetro — isso é "passagem por valor". Modificar o parâmetro dentro da função não afeta o argumento.

C
void try_change(int n) {
    n = 100;
}

int main(void) {
    int x = 5;
    try_change(x);
    printf("%d\n", x);
    return 0;
}

A saída ainda é 5, porque n é apenas uma cópia de x.

Valores de retorno

Uma função retorna um resultado a quem a chamou através do comando return. O tipo de retorno deve corresponder à declaração da função:

C
double circle_area(double r) {
    return 3.14159 * r * r;
}

Uma função pode retornar uma expressão diretamente sem armazená-la em uma variável primeiro. Uma vez que return é executado, a função termina imediatamente; o código subsequente não é executado:

C
int max(int a, int b) {
    if (a > b) {
        return a;
    }
    return b;
}

Declaração de função (protótipo)

Se uma função é definida após o ponto onde é chamada, o compilador não reconhece o nome da função e produzirá um erro ou assumirá implicitamente que ela retorna int. A solução é declarar o protótipo da função antes da chamada:

C
int add(int a, int b);

int main(void) {
    int result = add(3, 5);
    return 0;
}

int add(int a, int b) {
    return a + b;
}

Uma declaração inclui apenas o cabeçalho seguido de ponto e vírgula; o corpo da função não é necessário. Os nomes dos parâmetros podem ser omitidos:

C
int add(int, int);

No entanto, manter os nomes dos parâmetros melhora a legibilidade e é recomendado.

💡 Dica: Em projetos reais, declarações de funções são tipicamente colocadas em arquivos de cabeçalho (.h), e definições de funções em arquivos fonte (.c).

Funções void

Funções que não precisam retornar um valor usam void como tipo de retorno:

C
void print_line(int len) {
    int i;
    for (i = 0; i < len; i++) {
        printf("-");
    }
    printf("\n");
}

Em uma função void, return pode ser omitido, ou return; pode ser usado para sair antecipadamente:

C
void greet(int hour) {
    if (hour < 0 || hour > 23) {
        return;
    }
    if (hour < 12) {
        printf("Good morning\n");
    } else {
        printf("Good afternoon\n");
    }
}
⚠️ Atenção: Uma função void não pode retornar um valor; return 5; causará erro de compilação. Da mesma forma, todo caminho de execução em uma função não-void deve ter um return com o tipo correto.

Exemplo

Determine se um inteiro é par:

C
#include <stdio.h>

int is_even(int n) {
    return n % 2 == 0;
}

int main(void) {
    int nums[] = {3, 4, 7, 8, 11, 16};
    int i;
    int len = sizeof(nums) / sizeof(nums[0]);

    for (i = 0; i < len; i++) {
        printf("%d is %s\n", nums[i], is_even(nums[i]) ? "even" : "odd");
    }

    return 0;
}
▶ Experimente
TEXT
3 is odd
4 is even
7 is odd
8 is even
11 is odd
16 is even

O comando return em detalhes

Uma função pode ter múltiplos comandos return, mas apenas um é executado por chamada. return tem dois efeitos:

  1. Retornar um valor a quem chamou
  2. Terminar imediatamente a execução da função
C
const char *grade(int score) {
    if (score >= 90) return "Excellent";
    if (score >= 80) return "Good";
    if (score >= 60) return "Pass";
    return "Fail";
}

O valor de retorno é copiado para o ponto da chamada. Para tipos básicos (int, double, etc.), o custo da cópia é insignificante. Após uma função retornar, suas variáveis locais não existem mais, então você não deve retornar um ponteiro para uma variável local.

Funções com múltiplos parâmetros

Uma função pode ter múltiplos parâmetros, separados por vírgulas. O número e os tipos dos argumentos devem corresponder exatamente aos parâmetros:

C
double bmi(double weight, double height) {
    return weight / (height * height);
}

Os argumentos são correspondidos aos parâmetros por posição:

C
double result = bmi(70.0, 1.75);
⚠️ Atenção: Quando os tipos do argumento e do parâmetro não correspondem, o compilador pode realizar conversão implícita ou emitir um aviso. É melhor manter os tipos consistentes.

Exemplo

Calcule o número de dias entre duas datas (versão simplificada, ignorando anos bissextos e diferenças de meses, apenas demonstrando funções com múltiplos parâmetros):

C
#include <stdio.h>

int day_of_year(int year, int month, int day) {
    int days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    int total = 0;
    int m;

    for (m = 1; m < month; m++) {
        total += days_in_month[m];
    }
    total += day;

    return total;
}

int days_between(int y1, int m1, int d1, int y2, int m2, int d2) {
    int first = day_of_year(y1, m1, d1);
    int second = day_of_year(y2, m2, d2);
    int diff = second - first;
    if (diff < 0) diff = -diff;
    return diff;
}

int main(void) {
    int d = days_between(2025, 3, 1, 2025, 6, 15);
    printf("%d days apart\n", d);
    return 0;
}
▶ Experimente
TEXT
106 days apart

❓ Perguntas Frequentes

P: Um parâmetro pode ter o mesmo nome que um argumento? R: Sim, são variáveis em escopos diferentes e não afetam uma à outra. No entanto, para evitar confusão, é recomendável usar nomes diferentes.

P: Uma função pode omitir o tipo de retorno? R: Em C89, omitir o tipo de retorno assume int como padrão. C99 e posteriores exigem um tipo de retorno explícito. Sempre especificar o tipo de retorno é um bom hábito.

P: Qual a utilidade de return; em uma função void? R: É usado para sair da função antecipadamente, ignorando a lógica subsequente. É semelhante ao break em um laço.

P: Uma função pode retornar múltiplos valores? R: Uma função C só pode retornar um valor. Para retornar múltiplos resultados, use parâmetros de ponteiro, structs ou vetores.

📖 Resumo

📝 Exercícios

  1. Escreva uma função int max3(int a, int b, int c) que retorne o maior de três inteiros.
  2. Escreva uma função void swap_wrong(int a, int b) que tente trocar dois valores. Verifique em main se obteve sucesso, e explique o porquê.
  3. Escreva uma função int digit_sum(int n) que calcule a soma dos dígitos de um inteiro positivo (ex.: 123 retorna 6). Teste-a em main.
100%