← Aulas

Funções em Linguagem C

Declaração, definição, chamada e passagem de parâmetros por valor e por referência.

Disciplina:Introdução à Programação em C Público-alvo:Licenciatura em Eng. Electrónica e Telecomunicações Carga Horária:2 horas (1h teórica + 1h prática) Docente:Isac Osvaldo de Venâncio Daniel

Objectivos da Aula

02

Ao final desta aula, o estudante deverá ser capaz de:

  • Compreender o conceito de função e a sua importância na modularização de programas em C.
  • Declarar protótipos de funções e definir o seu corpo corretamente.
  • Chamar funções, passando argumentos e tratando valores de retorno.
  • Distinguir passagem de parâmetros por valor e por referência (ponteiros).
  • Aplicar funções na construção de bibliotecas e drivers para sistemas embarcados.
🎯
As funções são a base da programação modular e da reutilização de código — competências essenciais na engenharia de firmware.

Conteúdo Programático

03

1 · Fundamentos

  • O que é uma função?
  • Anatomia de uma função
  • Vantagens da modularização

2 · Declaração / Definição / Chamada

  • Protótipo (declaração)
  • Corpo da função (definição)
  • Chamada e valor de retorno

3 · Passagem de Parâmetros

  • Por valor (cópia)
  • Por referência (ponteiros)
  • Comparação e casos de uso

4 · Aplicações

  • Bibliotecas e drivers
  • Exemplos em sistemas embarcados
  • Exercícios práticos

O que é uma Função?

04

Uma função é um bloco de código com um nome, que executa uma tarefa específica e pode ser chamada em qualquer parte do programa.

Em C, todo programa é uma colecção de funções. A execução começa sempre pela função main().

♻️ Reutilização

Escreve-se o código uma vez e usa-se em vários locais.

📦 Modularização

Divide-se o problema em partes mais pequenas e gerenciáveis.

🧪 Testabilidade

Permite testar cada função isoladamente antes de integrar.

📖 Legibilidade

Um bom nome de função documenta a intenção do código.

🛠️ Manutenção

Corrigir um erro num único lugar afecta todos os chamadores.

⚡ Performance

Evita duplicação de código, reduzindo o tamanho do binário.

Anatomia de uma Função

05
tipoRetorno nomeDaFuncao(tipo1 param1, tipo2 param2) {
    // corpo da função
    return valor;
}
ElementoDescrição
tipoRetornoTipo de valor devolvido (int, float, char, void…).
nomeDaFuncaoIdentificador único (letra/underscore inicial).
param1, param2Lista de parâmetros (pode ser vazia ou void).
{ ... }Corpo com as instruções a executar.
returnDevolve o valor ao ponto de chamada e termina a função.
💡
O tipo void significa "nada". Usamos void como retorno quando a função não devolve valor, e (void) como parâmetro quando a função não recebe nada.

Declaração (Protótipo)

06

O protótipo informa o compilador sobre a existência da função, o seu nome, tipo de retorno e parâmetros — antes de a função ser usada.

// Protótipo (termina com ponto-e-vírgula)
int  soma(int a, int b);
void ligaLed(int numero);
float media(float x, float y);
✅
Boas práticas: declarar todos os protótipos no início do ficheiro .c ou num ficheiro .h. Isto resolve o problema de referência circular.
⚠️
Se a função for definida antes de ser chamada, o protótipo é opcional. Se for definida depois, o protótipo é obrigatório.
#include <stdio.h>

int soma(int a, int b);  // protótipo

int main(void) {
    printf("%d\n", soma(3, 4));
    return 0;
}

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

Definição da Função

07

A definição contém o corpo com os comandos que a função executa quando for chamada.

int soma(int a, int b) {
    int resultado;
    resultado = a + b;
    return resultado;
}

void desenhaLinha(void) {
    int i;
    for (i = 0; i < 10; i++) {
        printf("*");
    }
    printf("\n");
}

✅ Regras

  • Funções não podem ser definidas dentro de outras funções.
  • O return devolve o valor e termina a função.
  • Uma função pode ter vários return.
  • Se for void, pode-se omitir o return.

🚫 Erros comuns

  • Devolver tipo diferente do declarado.
  • Esquecer o return numa função não-void.
  • Colocar ponto-e-vírgula depois de }.
  • Confundir tipo de retorno com tipo dos parâmetros.

Chamada da Função

08

Para executar uma função, escreve-se o seu nome seguido de parênteses com os argumentos. O fluxo salta para a função, executa-a e volta ao ponto de chamada.

int main(void) {
    int r;
    r = soma(3, 4);  // chamada → r = 7
    desenhaLinha();      // chamada sem retorno
    return 0;
}
main()
→
soma(3, 4)
→
retorna 7
→
main()
📌
A chamada tem de corresponder ao protótipo: mesmo número e tipo de argumentos.
// Chamadas aninhadas — a função pode chamar outras funções
float mediaFinal(float a, float b) {
    return media(a, b) * 1.1;
}

Passagem de Parâmetros — Introdução

09

Quando uma função é chamada, os valores passados são copiados para os parâmetros formais declarados na função. Este é o mecanismo padrão da linguagem C: passagem por valor.

📥 Parâmetros formais

Declarados na definição da função. São variáveis locais que existem apenas dentro da função.

int soma(int a, int b)
          ↑     ↑
       formais

📤 Argumentos reais

Valores ou variáveis passados na chamada. As suas cópias é que chegam à função.

soma(3, x);
      ↑  ↑
   reais
⚠️
Importante: Em C não existe passagem por referência "nativa". O que se costuma chamar de "passagem por referência" é, na realidade, passagem de ponteiros por valor — que simulam o efeito de referência.

Passagem por Valor

10

A função recebe uma cópia do valor do argumento. Alterações feitas dentro da função não afectam a variável original.

void duplica(int n) {
    n = n * 2;
    printf("Dentro: n = %d\n", n);
}

int main(void) {
    int x = 10;
    duplica(x);
    printf("Fora: x = %d\n", x);   // 10 (não mudou!)
    return 0;
}
Variável original (main)
x100x1000
Cópia dentro de duplica()
n10 → 200x2000
✅
Vantagens: simples, segura, o chamador fica protegido.
Desvantagens: cópias de estruturas grandes consomem memória e tempo.

Passagem por Referência (Ponteiros)

11

Em vez de passar o valor, passamos o endereço da variável (com &). Dentro da função usamos um ponteiro para aceder e modificar o valor original (com *).

void duplica(int *n) {
    *n = (*n) * 2;
}

int main(void) {
    int x = 10;
    duplica(&x);
    printf("x = %d\n", x);   // 20
    return 0;
}
Variável original (main)
x10 → 200x1000
Parâmetro dentro de duplica()
n0x10000x2000
🧠
O ponteiro n é passado por valor (copia-se o endereço), mas como esse endereço aponta para x, alterar *n altera x.

Por Valor vs. Por Referência

12
Aspecto Por Valor Por Referência (ponteiros)
Sintaxe na chamadaf(x)f(&x)
Parâmetro formalint xint *x
O que é copiadoO valor da variávelO endereço da variável
Alterações dentro da funçãoNão afectam o originalAfectam o original
Consumo de memóriaAlto (cópias grandes)Baixo (só o endereço)
SegurançaAlta (isolamento)Requer cuidado
Uso típicoValores pequenosStructs, arrays, retorno múltiplo
🎯
Regra prática: use por valor para tipos simples e por referência para estruturas grandes ou quando precise de "devolver" mais do que um valor.

Devolver Múltiplos Valores

13

Em C, uma função devolve um único valor com return. Para devolver vários, usamos ponteiros como parâmetros de saída.

void calc(int a, int b, int *soma, int *prod) {
    *soma = a + b;
    *prod = a * b;
}

int main(void) {
    int s, p;
    calc(3, 4, &s, &p);
    printf("Soma = %d, Produto = %d\n", s, p);
    return 0;
}
🔁
Outro exemplo clássico é a troca de valores (swap):
void troca(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int x = 5, y = 9;
troca(&x, &y);   // x = 9, y = 5

Escopo e Tempo de Vida

14

🔒 Variáveis locais

  • Declaradas dentro de uma função.
  • Existem apenas enquanto a função está a executar.
  • Guardadas na pilha (stack).
  • Não são inicializadas automaticamente.

🌍 Variáveis globais

  • Declaradas fora de qualquer função.
  • Acessíveis em qualquer parte do programa.
  • Guardadas numa região fixa da RAM.
  • Devem ser usadas com moderação.
int contadorGlobal;

void incrementa(void) {
    static int contadorLocal = 0;
    contadorLocal++;
    contadorGlobal++;
    printf("Local: %d, Global: %d\n", contadorLocal, contadorGlobal);
}
⚠️
O modificador static faz com que uma variável local mantenha o seu valor entre chamadas à função, sem se tornar global.

Bibliotecas em C

15

Uma biblioteca é um conjunto de funções com uma funcionalidade comum, organizada em dois ficheiros: .h (cabeçalho) e .c (implementação).

📄 math.h

#ifndef MATH_H
#define MATH_H

int   quadrado(int x);
int   fatorial(int n);
float grausParaRad(float g);
void  raizes(float a, float b,
            float c, float *x1, float *x2);

#endif

📄 math.c

#include "math.h"

int quadrado(int x) {
    return x * x;
}

float grausParaRad(float g) {
    return g * 2 * 3.14159 / 360;
}
#include "math.h"

int main(void) {
    printf("%d\n", quadrado(5));   // 25
    return 0;
}
🛡️
A "guarda" #ifndef MATH_H evita referências circulares e inclusões repetidas do mesmo header.

Funções em Sistemas Embarcados

16

Nos sistemas embarcados, as funções são usadas para abstrair o acesso ao hardware e criar camadas de software reutilizáveis.

Exemplo 1: Driver de LED

// led.h
void ledInit(int pino);
void ledOn(int pino);
void ledOff(int pino);
void ledToggle(int pino);

// led.c
void ledOn(int pino) {
    digitalWrite(pino, HIGH);
}

Exemplo 2: Leitura filtrada de sensor

void lerSensorFiltrado(int *valorFiltrado, int nAmostras) {
    long soma = 0;
    int i;
    for (i = 0; i < nAmostras; i++) {
        soma += adRead(0);
    }
    *valorFiltrado = soma / nAmostras;
}
📚
Este padrão é usado em bibliotecas do livro (lcd.h, keypad.h, ssd.h, ad.h, timer.h).

Erros Frequentes com Funções

17

🚫 Erro 1: Esquecer o protótipo

int main(void) {
    soma(3, 4);   // erro se soma()
                    // ainda não foi vista
}

🚫 Erro 2: Confundir valor e ponteiro

void f(int *p) { *p = 5; }

int x;
f(x);    // ❌ faltou o &
f(&x);   // ✅

🚫 Erro 3: Esquecer o return

int soma(int a, int b) {
    a + b;   // ❌ sem return
}

🚫 Erro 4: Modificar parâmetro por valor

void duplica(int n) {
    n = n * 2;   // só altera a cópia
}
🔍
Dica: ligue os avisos (warnings) do compilador. Muitos erros são detectados nessa fase.

Exercícios Propostos

18

1 · Soma e Produto

Crie soma e produto que recebam dois inteiros e devolvam o resultado.

2 · Verificar Par

Crie int isPar(int n) que retorne 1 se n é par.

3 · Trocar Valores (Swap)

Implemente void troca(int *a, int *b) usando ponteiros.

4 · Mínimo e Máximo

Crie void minMax(int v[], int n, int *min, int *max).

5 · Raízes Quadráticas

Crie void raizes(float a, float b, float c, float *x1, float *x2).

6 · Biblioteca de Conversão

Crie conv.h/conv.c com funções: celsiusParaFahrenheit, kmParaMilhas, kgParaLibras.

7 · Driver de LED

Implemente ledInit, ledOn, ledOff, ledToggle.

8 · Média Móvel

Implemente void mediaMovel(int *v, int n, int tam, float *resultado).

Resumo e Considerações Finais

19

📌 Conceitos-Chave

  • Funções = blocos reutilizáveis com nome.
  • Protótipo informa; definição implementa; chamada executa.
  • Em C, todos os parâmetros são passados por valor.

🔧 Por Valor

  • Copia o valor.
  • Não altera o original.
  • Ideal para tipos simples.

🧷 Por Referência

  • Passa o endereço (&).
  • Altera o original (*).
  • Útil para arrays, structs e retorno múltiplo.

🚀 Próximos Passos

  • Criar bibliotecas (.h + .c).
  • Estudar ponteiros em profundidade.
  • Explorar ponteiros de função.

Bibliografia

20

📚 Bibliografia Principal

ASCENCIO, Ana Fernanda Gomes; VENERUCH, Edilene Aparecida.
Fundamentos da Programação de Computadores: algoritmos, PASCAL, C/C++ (padrão ANSI) e JAVA.
3. ed. Pearson Editora, 2014.

📚 Bibliografia Complementar

ALMEIDA, Rodrigo Maximiano Antunes de; MORAES, Carlos Henrique Valério; SERAPHIM, Thatyana de Faria Piola.
Programação de Sistemas Embarcados: Desenvolvendo Software para Microcontroladores em Linguagem C.
Elsevier, 2016. (Capítulo 9)

📚 Material Didático

Material didático do ISPSongo — Plano Analítico de Introdução à Programação em C.

🎓
Instituto Superior Politécnico de Songo — Divisão de Engenharia
Licenciatura em Engenharia Electrónica e Telecomunicações

Fim da Aula

Obrigado! Bons estudos e boa programação em C.

Próxima aula:Ponteiros e Alocação Dinâmica Prática:Resolver exercícios 1 a 8
← Voltar à lista de aulas