Escrevendo C como um profissional
Os hábitos, as ferramentas e os truques que separam o código que funciona hoje do código que continua funcionando.
- Dividir um programa em arquivos
.ce.hcom include guards - Usar avisos, sanitizers e um depurador para encontrar bugs cedo
- Aplicar hábitos defensivos:
const, verificação de limites e posse clara da memória
Agora você conhece o núcleo do C. Esta última aula trata de como os programadores de C experientes trabalham, porque em C são os hábitos que mantêm os programas seguros. Nada disto é extra - é o que "saber C" significa na prática.
Dividindo um programa em arquivos
Quando um programa passa de algumas centenas de linhas, divida-o em módulos: um cabeçalho (.h) que declara o que o módulo oferece e um arquivo-fonte (.c) que o implementa.
1#ifndef STATS_H
2#define STATS_H
3
4#include <stddef.h>
5
6double mean(const double values[], size_t count);
7double maximum(const double values[], size_t count);
8
9#endif1#include "stats.h"
2
3double mean(const double values[], size_t count) {
4 double total = 0.0;
5 for (size_t i = 0; i < count; i++) {
6 total += values[i];
7 }
8 return count > 0 ? total / count : 0.0;
9}
10
11double maximum(const double values[], size_t count) {
12 double best = values[0];
13 for (size_t i = 1; i < count; i++) {
14 if (values[i] > best) {
15 best = values[i];
16 }
17 }
18 return best;
19}- O
main.centão escreve#include "stats.h"(aspas para os seus próprios cabeçalhos, sinais de menor/maior para os do sistema) e chamamean. - As linhas
#ifndef STATS_H / #define STATS_H / #endifsão um include guard: se o cabeçalho for incluído duas vezes, a segunda cópia é pulada. - Gere com
gcc -Wall -Wextra main.c stats.c -o app. Projetos maiores usam um Makefile (ou CMake) para que só os arquivos alterados sejam recompilados. - As funções privadas de um arquivo devem ser marcadas como
static, o que as esconde dos outros arquivos.
Deixe as ferramentas pegarem os bugs
| Ferramenta | Pega | Como |
|---|---|---|
| Avisos do compilador | tipos que não combinam, variáveis não usadas, returns faltando, = vs. == | -Wall -Wextra (e -Werror para transformá-los em erros) |
| AddressSanitizer | acesso fora dos limites, uso depois do free, vazamentos | -fsanitize=address -g |
| UndefinedBehaviorSanitizer | overflow com sinal, deslocamentos inválidos, ponteiros desalinhados | -fsanitize=undefined |
| Depurador (gdb / lldb) | onde e por que travou; avançar linha por linha | compile com -g, rode gdb ./app |
| Analisadores estáticos | bugs visíveis sem rodar | clang --analyze, cppcheck |
Hábitos defensivos
- Inicialize tudo. Variáveis e ponteiros recebem um valor ao serem declarados.
- Carregue os tamanhos junto com os dados. Todo parâmetro array vem com o seu tamanho; use
sizeofem vez de números fixos. - Use funções com limite.
snprintf,fgets,%99snoscanf- nunca uma escrita sem limite. - Verifique os valores de retorno.
malloc,fopen,scanfe companhia dizem quando falham; preste atenção. - Deixe a posse óbvia. Para cada
malloc, deve ficar claro qual função chama ofree. Comente onde não for óbvio. - Use
constà vontade. Ele documenta a intenção e transforma escritas acidentais em erros de compilação. - Mantenha as funções pequenas. Funções pequenas são mais fáceis de testar, e os bugs têm menos lugares para se esconder.
Para onde ir agora
- Leia The C Programming Language (K&R). Curto, preciso e ainda o clássico.
- Construa algo de verdade: uma aventura de texto, uma lista de tarefas que salva num arquivo, um shell minúsculo, um Jogo da Vida, uma ferramenta de hex dump.
- Aprenda estruturas de dados em C: listas ligadas, pilhas, tabelas hash - agora você tem todas as ferramentas (structs, ponteiros, malloc) para construí-las.
- Explore sistemas: conceitos de sistemas operacionais, chamadas de sistema do Linux ou microcontroladores com um Arduino ou um Raspberry Pi Pico.
- Pergunte e ajude na discussão abaixo de cada aula. Explicar uma ideia para outra pessoa é o jeito mais rápido de encontrar as lacunas no seu próprio entendimento.
Principais conclusões
Divida os programas em
.h(declarações, com include guards) e.c(definições); marque comostaticas funções privadas de um arquivo.Ligue os avisos e os sanitizers desde o primeiro dia e aprenda a usar um depurador - eles encontram a maioria dos bugs mais rápido do que você.
Inicializar, limitar, verificar e definir a posse: os hábitos defensivos que tornam os programas em C seguros.
Quiz da aula
5 perguntas · aprovação com 4 acertos · até 50 XP
Ao passar, você conclui a aula e mantém sua sequência. As perguntas erradas voltarão em sessões de revisão.
Pratique: escreva código em C
Estes exercícios rodam de verdade. Escreva o programa, clique em “Executar testes” e leia o que o compilador informa: aprender a ler as mensagens do compilador é metade do aprendizado de C.
Uma saudação com limite
Implemente void make_greeting(char *out, size_t size, const char *name) para que escreva Hello, <name>! em out sem nunca escrever mais que size bytes (truncando se necessário). Use snprintf.
A main lê um nome e a chama com um buffer pequeno de 16 bytes, então nomes longos precisam ser cortados com segurança. Para Ada, imprima Hello, Ada!; para Bartholomew, imprima Hello, Bartholo (15 caracteres + terminador).
- Nome curto
- Nome longo é truncado
Seu código é compilado com gcc 14 (-Wall -Wextra) e executado no Compiler Explorer (godbolt.org), um serviço público gratuito.
Dúvidas sobre esta lição
Travou em algum ponto? Pergunte. Descobriu algo? Compartilhe. Explicar também é uma ótima forma de aprender.
Carregando publicações…