📚 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.
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 |
& (endereço de) e * (desreferência).trocar(int *a, int *b), provando que a troca afeta as variáveis originais do main.return, que só devolve um único valor.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:
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.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.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
O mesmo do Miniprojeto 01: gcc 8 ou mais novo. No Windows, rode chcp 65001 se os emojis aparecerem quebrados.
🎯 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.
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:
passing argument 1 of 'trocar' makes pointer from integer: você passou x em vez de &x.int *temp = a; a = b; b = temp;, que troca só as cópias dos ponteiros, não os valores apontados. Falta o *.🎯 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).
🎯 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:
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.
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.
📋 Projetos do curso de C | 📚 Teoria do Capítulo 13 | 🗂️ Hub de projetos