📚 Capítulo do curso: 13 — Ponteiros Fundamentais, Endereçamento (&/*) e Passagem por Referência da Especialização em Sistemas com C. Leia o capítulo antes de começar.

👉 Miniprojeto C 13 — Passagem por Referência com Ponteiros

Manipulação direta de memória com ponteiros: troque valores de verdade entre variáveis e retorne mais de um resultado de uma função.

⏱️ Tempo estimado 📦 Você vai entregar ✅ Pronto quando
40 min main.c x e y trocam de valor no main e min_max devolve 12 e 83

Diagrama do 👉 Miniprojeto C 13 — Passagem por Referência com Ponteiros

🎯 Objetivos

📋 O problema

Uma função em C só pode return um único valor. Mas e quando você precisa que uma função calcule dois resultados — como o menor e o maior de três números? A resposta é a passagem por referência: em vez de passar o valor de uma variável, você passa o endereço dela, e a função escreve diretamente naquele endereço.

O programa (main.c) deve:

  1. Implementar void trocar(int *a, int *b), que troca os valores de duas variáveis int via ponteiro, e demonstrar, no main, os valores antes e depois da chamada.
  2. Implementar void min_max(int a, int b, int c, int *menor, int *maior), que recebe três números por valor e escreve o menor e o maior deles nos endereços apontados por menor e maior.
  3. Demonstrar as duas funções no main com valores fixos, imprimindo o resultado de forma clara.
ID Requisito
RF01 O programa deve compilar sem nenhum aviso com gcc -Wall -Wextra -Wpedantic -std=c17.
RF02 Deve implementar void trocar(int *a, int *b) usando exatamente os operadores & (no main, para passar o endereço) e * (dentro da função, para acessar o valor apontado).
RF03 A chamada a trocar deve alterar de fato as variáveis originais do main — o programa deve imprimir os valores antes e depois da troca, provando que não foi uma cópia.
RF04 Deve implementar void min_max(int a, int b, int c, int *menor, int *maior) que calcula corretamente o menor e o maior entre três números, escrevendo os resultados via ponteiro.
RF05 O main deve demonstrar min_max com três números fixos, imprimindo o menor e o maior calculados.
graph LR
    A["main(): x, y, n1, n2, n3"] --> B["trocar(&x, &y)\npassagem por referencia"]
    A --> C["min_max(n1,n2,n3,&menor,&maior)\ndois resultados via ponteiro"]
    B --> D["Relatorio final:\nantes/depois + menor/maior"]
    C --> D

    style B fill:#0284c7,stroke:#38bdf8,color:#ffffff
    style C fill:#0d9488,stroke:#2dd4bf,color:#ffffff
    style D fill:#059669,stroke:#34d399,color:#ffffff

🧰 Ambiente

O mesmo do Miniprojeto 01: gcc 8 ou mais novo. No Windows, rode chcp 65001 se os emojis aparecerem quebrados.


Passo 1 — Compilar o esqueleto

🎯 Objetivo: partir de um código que compila e roda, antes de escrever qualquer linha.

⌨️ Faça: crie a pasta c_mini_13, salve o código abaixo como main.c e rode:

gcc -Wall -Wextra -Wpedantic -std=c17 main.c -o app
./app          # Linux/macOS
.\app.exe      # Windows (PowerShell)

📄 src/esqueleto.c

/*
 * Miniprojeto 13: Gerenciador de Variaveis com Passagem por Referencia
 * Capitulo 13: ponteiros basicos, &, *, passagem por referencia.
 */
#include <stdio.h>
#include <stdlib.h>

void trocar(int *a, int *b) {
    (void)a; (void)b; // stub: apague esta linha ao implementar
    // TODO 1: troque os valores apontados por "a" e "b" usando uma
    // variavel temporaria e o operador de desreferencia (*a, *b).
}

void min_max(int a, int b, int c, int *menor, int *maior) {
    (void)a; (void)b; (void)c; (void)menor; (void)maior; // stub: apague esta linha ao implementar
    // TODO 2: compare a, b e c (parametros normais, por valor) e escreva
    // o menor e o maior nos enderecos apontados por "menor" e "maior".
}

int main(void) {
    int x = 10, y = 25;

    printf("--- Demonstracao 1: troca por referencia (swap) ---\n");
    printf("Antes  da troca: x = %d, y = %d\n", x, y);
    // TODO 3: chame trocar passando os enderecos de x e y (operador &).
    printf("Depois da troca: x = %d, y = %d\n", x, y);

    printf("\n--- Demonstracao 2: multiplos retornos via ponteiro ---\n");
    int n1 = 47, n2 = 12, n3 = 83;
    int menor = 0, maior = 0; // so mudam quando min_max escrever neles
    // TODO 4: chame min_max passando n1, n2, n3 por valor e os enderecos
    // de "menor" e "maior".
    printf("Numeros: %d, %d, %d\n", n1, n2, n3);
    printf("Menor = %d | Maior = %d\n", menor, maior);

    return EXIT_SUCCESS;
}

✅ Checkpoint: zero avisos do gcc, e a saída é:

🖥️ Saída esperada:

--- Demonstracao 1: troca por referencia (swap) ---
Antes  da troca: x = 10, y = 25
Depois da troca: x = 10, y = 25

--- Demonstracao 2: multiplos retornos via ponteiro ---
Numeros: 47, 12, 83
Menor = 0 | Maior = 0

Repare que as linhas Antes e Depois são iguais, e que menor e maior continuam 0: as funções ainda não escrevem em lugar nenhum.

💡 As linhas (void)a; e similares silenciam o aviso de parâmetro não usado enquanto a função é um stub. Apague cada uma ao implementar a função.


Passo 2 — trocar por referência (TODO 1 e 3)

🎯 Objetivo: alterar variáveis do main a partir de outra função.

⌨️ Faça: em trocar, int temp = *a; *a = *b; *b = temp;. No main, chame trocar(&x, &y);.

✅ Checkpoint: Depois da troca: x = 25, y = 10.

🧯 Se der errado:


Passo 3 — Dois resultados via ponteiro (TODO 2 e 4)

🎯 Objetivo: “devolver” mais de um valor escrevendo em endereços recebidos.

⌨️ Faça: em min_max, comece com *menor = a; *maior = a; e ajuste com b e c usando if. No main, chame min_max(n1, n2, n3, &menor, &maior);.

✅ Checkpoint: Menor = 12 | Maior = 83.

🧯 Se der errado: Menor = 0 mesmo depois de implementar: dentro da função você escreveu menor = a (muda a cópia do ponteiro) em vez de *menor = a (muda a variável do main).


Passo final — Conferir com o gabarito

🎯 Objetivo: validar a saída completa e o código de retorno.

✅ Checkpoint: a saída é esta, e o código de retorno é 0 (echo $? no Linux/macOS ou echo $LASTEXITCODE no PowerShell):

🖥️ Saída esperada:

====================================================
 ⚡ Gerenciador de Variaveis com Passagem por Referencia
====================================================

--- Demonstracao 1: troca por referencia (swap) ---
Antes  da troca: x = 10, y = 25
Depois da troca: x = 25, y = 10

--- Demonstracao 2: multiplos retornos via ponteiro ---
Numeros: 47, 12, 83
Menor = 12 | Maior = 83
====================================================

Só abra o gabarito depois de chegar até aqui:

🔑 Ver gabarito: src/main.c

📄 src/main.c

/*
 * Miniprojeto 13: Gerenciador de Variaveis com Passagem por Referencia
 * Especializacao em Engenharia de Sistemas em C
 * Capitulo 13: ponteiros basicos, &, *, passagem por referencia.
 */
#include <stdio.h>
#include <stdlib.h>

void trocar(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

void min_max(int a, int b, int c, int *menor, int *maior) {
    *menor = a;
    *maior = a;

    if (b < *menor) {
        *menor = b;
    }
    if (b > *maior) {
        *maior = b;
    }
    if (c < *menor) {
        *menor = c;
    }
    if (c > *maior) {
        *maior = c;
    }
}

int main(void) {
    int x = 10, y = 25;

    printf("====================================================\n");
    printf(" ⚡ Gerenciador de Variaveis com Passagem por Referencia\n");
    printf("====================================================\n");

    printf("\n--- Demonstracao 1: troca por referencia (swap) ---\n");
    printf("Antes  da troca: x = %d, y = %d\n", x, y);
    trocar(&x, &y);
    printf("Depois da troca: x = %d, y = %d\n", x, y);

    printf("\n--- Demonstracao 2: multiplos retornos via ponteiro ---\n");
    int n1 = 47, n2 = 12, n3 = 83;
    int menor, maior;
    min_max(n1, n2, n3, &menor, &maior);
    printf("Numeros: %d, %d, %d\n", n1, n2, n3);
    printf("Menor = %d | Maior = %d\n", menor, maior);

    printf("====================================================\n");

    return EXIT_SUCCESS;
}

Por que isso importa: em trocar(&x, &y), o main passa os endereços de x e y, não seus valores. Dentro de trocar, a e b são ponteiros que apontam para essas mesmas posições de memória — por isso *a = *b de fato altera y do ponto de vista do main. Se trocar recebesse int a, int b (por valor), a troca só existiria dentro da função e desapareceria ao retornar.


🏆 Desafio

Implemente void ordenar_tres(int *a, int *b, int *c), que recebe os endereços de três variáveis e as deixa em ordem crescente, reaproveitando trocar (no máximo três chamadas a trocar resolvem qualquer combinação de três valores). Teste com n1=47, n2=12, n3=83 do próprio main e confirme que, após a chamada, n1 <= n2 <= n3.

✅ Checkpoint: depois de ordenar_tres(&n1, &n2, &n3), o main imprime 12, 47, 83.


🧭 Navegação

📋 Projetos do curso de C | 📚 Teoria do Capítulo 13 | 🗂️ Hub de projetos