Pular para conteúdo

Semana 01 — Primeiros passos em C

Nesta semana

Unidade 1 · Seg 10/08 · Qua 12/08 · Sex 14/08

Esta é a semana de fundação da disciplina. Vamos retomar o que você viu em Pensamento Computacional e mostrar como aquelas ideias abstratas (algoritmos, variáveis, decisões) ganham forma concreta na linguagem C. Ao final, você terá escrito, compilado e executado seus primeiros programas de verdade — e, mais importante, vai entender o que acontece por baixo quando isso ocorre.

Leia com calma e, sobretudo, digite e execute cada exemplo. Programação não se aprende só lendo: aprende-se com as mãos no teclado.

🎯 Objetivos de aprendizagem

Ao final desta semana, você deverá ser capaz de:

  • explicar, em linhas gerais, como um computador executa um programa e o caminho que vai do código-fonte ao programa em execução;
  • descrever o papel do compilador e as etapas da compilação;
  • escrever, compilar e executar um programa simples em C, reconhecendo cada parte da sua estrutura;
  • explicar o que é uma variável, como ela se relaciona com a memória e por que toda variável em C tem um tipo;
  • escolher o tipo adequado (int, float, double, char) e usar os especificadores de formato corretos na entrada e na saída;
  • construir expressões com operadores aritméticos, relacionais e lógicos, prevendo seu resultado (inclusive os casos "traiçoeiros", como a divisão inteira e a precedência de operadores).

📖 Segunda — Estudo do conteúdo

1. Como um computador executa um programa

1.1 O que é, afinal, um programa?

Um programa é uma sequência de instruções que descreve, sem ambiguidade, uma tarefa a ser executada por um computador. Em Pensamento Computacional você aprendeu a pensar a solução — decompor um problema, descrever um algoritmo, testar a lógica. Aqui damos o passo seguinte: expressar esse algoritmo em uma linguagem que a máquina consegue, em última instância, executar.

Pense na diferença entre uma receita de bolo (o algoritmo: a ideia, os passos) e a receita escrita em um idioma específico que o cozinheiro entende (o programa em uma linguagem de programação). O algoritmo é o mesmo; a linguagem muda. Nesta disciplina, o "idioma" será o C.

1.2 O hardware por trás de tudo

Para entender por que programamos do jeito que programamos, ajuda conhecer, em alto nível, as peças principais de um computador:

Componente Papel Analogia
CPU (processador) Executa as instruções, uma após a outra, e faz os cálculos. O "cozinheiro" que segue a receita.
Memória RAM Guarda temporariamente os dados e as instruções do programa em execução. Rápida, mas volátil (apaga ao desligar). A bancada onde os ingredientes ficam à mão.
Armazenamento (HD/SSD) Guarda arquivos de forma permanente. Mais lento que a RAM. A despensa/geladeira.
Dispositivos de E/S Teclado, mouse, tela, rede — a comunicação com o mundo. As mãos e a voz.

Quando você executa um programa, ele é carregado do armazenamento para a RAM, e a CPU passa a ler e executar suas instruções. As variáveis que você declara no seu código vivem, durante a execução, na memória RAM — guarde essa ideia, pois voltaremos a ela em toda a disciplina, culminando na Unidade 3 (ponteiros e memória).

Curiosidade 💡 — o modelo de von Neumann

A maioria esmagadora dos computadores atuais segue a arquitetura de von Neumann (anos 1940), na qual dados e instruções compartilham a mesma memória. É por isso que um programa é, em essência, "dados" que a CPU interpreta como "ordens". Essa ideia aparentemente simples é uma das mais poderosas da computação.

1.3 A máquina só entende zeros e uns

No nível mais baixo, a CPU só entende linguagem de máquina: números em binário (sequências de 0 e 1) que representam operações elementares ("some estes dois valores", "compare aqueles", "vá para tal instrução"). Programar diretamente assim seria inviável para humanos.

Por isso usamos linguagens de alto nível, como o C, que são próximas da nossa forma de raciocinar. Só que a CPU não entende C diretamente — é preciso traduzir. Essa tradução é o trabalho do compilador, que veremos a seguir.

Curiosidade 💡 — por que aprender C?

O C foi criado por Dennis Ritchie, nos Laboratórios Bell, por volta de 1972, para escrever o sistema operacional Unix. Mais de 50 anos depois, ele continua onipresente: sistemas operacionais (Linux, Windows, macOS têm núcleos em C), bancos de dados, jogos, sistemas embarcados (do seu micro-ondas ao carro) e até os interpretadores de outras linguagens (Python e muitas outras foram, originalmente, escritas em C). Aprender C ensina o que acontece "perto da máquina" — memória, eficiência, tipos — uma base que torna qualquer outra linguagem mais fácil depois.

1.4 Compilado × interpretado

Existem duas grandes estratégias para executar um programa escrito em linguagem de alto nível:

  • Compilação (o caso do C): um programa (o compilador) traduz todo o código-fonte, de uma vez, para um executável em linguagem de máquina. Depois, você roda esse executável quantas vezes quiser, sem precisar do código-fonte. Tende a gerar programas muito rápidos.
  • Interpretação (ex.: Python "puro"): um programa (o interpretador) lê e executa o código-fonte linha a linha, na hora. Mais flexível, porém geralmente mais lento.
flowchart LR
    subgraph compilado["Fluxo compilado (C)"]
    A["código-fonte<br/>programa.c"] -->|compilador| B["executável<br/>(linguagem de máquina)"]
    B --> R1["execução"]
    end

Como o C é compilado, todo programa passa por um ciclo escrever → compilar → executar. Vamos detalhar o "compilar".

2. Do código-fonte ao executável

Quando você manda "compilar" (seja apertando F9 no Code::Blocks, seja rodando o gcc no terminal — veja Ambiente e ferramentas), acontecem, nos bastidores, quatro etapas:

flowchart LR
    A["programa.c"] --> P["1. Pré-processador"]
    P --> C["2. Compilador"]
    C --> M["3. Montador (assembler)"]
    M --> L["4. Ligador (linker)"]
    L --> E["programa<br/>(executável)"]
  1. Pré-processamento: trata as linhas que começam com #. Por exemplo, o #include <stdio.h> é substituído pelo conteúdo do arquivo de cabeçalho stdio.h (que descreve funções como printf). Também expande #define (constantes/macros).
  2. Compilação: traduz o código C (já pré-processado) para Assembly, uma linguagem de baixo nível específica do processador.
  3. Montagem (assembler): converte o Assembly em código-objeto (binário), gerando um arquivo intermediário (.o).
  4. Ligação (linker): junta o seu código-objeto com o das bibliotecas usadas (por exemplo, a implementação real do printf) e produz o executável final.

Por que isso importa desde já

Boa parte dos "erros de compilação" que você verá nas próximas semanas aponta para uma dessas etapas. Erros de sintaxe (um ; esquecido) surgem na etapa 2; erros de undefined reference (função declarada mas não encontrada) surgem na etapa 4, a ligação. Saber em qual etapa o erro ocorre acelera muito a correção.

Curiosidade 💡 — código-fonte, objeto e executável

  • Código-fonte (.c): o texto que você escreve e lê.
  • Código-objeto (.o): binário, ainda "incompleto" (falta ligar bibliotecas).
  • Executável (programa no Linux/Mac, programa.exe no Windows): o binário final que o sistema operacional sabe rodar.

3. Anatomia de um programa em C

Todo programa começa por aqui. Vamos dissecar o clássico "Olá, mundo":

ola.c
#include <stdio.h>

int main(void) {
    printf("Ola, mundo!\n");
    return 0;
}

Linha a linha:

  • #include <stdio.h>diretiva de pré-processamento. Pede para "incluir" a biblioteca-padrão de entrada e saída (stdio = standard input/output), que contém, entre outras, a função printf. Sem essa linha, o compilador não conhece o printf. Repare que não termina com ; — diretivas # não são instruções comuns.
  • int main(void) — a função principal. Todo programa em C começa a executar pela main. O int antes do nome indica que ela devolve um número inteiro ao sistema operacional ao terminar; o void entre parênteses indica que ela não recebe parâmetros.
  • { ... } — as chaves delimitam o corpo (bloco) da função: tudo o que ela faz fica entre elas.
  • printf("Ola, mundo!\n"); — uma instrução que imprime um texto na tela. Toda instrução em C termina com ponto e vírgula ;.
  • return 0; — encerra a main e devolve o valor 0 ao sistema, convenção que significa "terminou tudo bem, sem erros". Um valor diferente de zero sinalizaria que algo deu errado.

Os dois erros mais comuns de quem está começando

  1. Esquecer o ; ao fim de uma instrução. O compilador quase sempre acusa o erro na linha seguinte, o que confunde — se a mensagem parece "sem sentido", olhe a linha de cima.
  2. Confundir chaves { } com parênteses ( ). Parênteses são para condições e parâmetros; chaves delimitam blocos.

Comentários: escreva para o seu 'eu do futuro'

Comentários são trechos ignorados pelo compilador, servem para explicar o código:

// comentário de uma linha (até o fim da linha)

/* comentário
   de várias linhas */
Comente o porquê de decisões não óbvias, não o óbvio. i = i + 1; // soma 1 a i não ajuda ninguém.

3.1 Compilando e executando

  • No Code::Blocks: salve o arquivo como ola.c e pressione F9 (compila e executa).
  • No terminal:
    gcc -Wall -std=c11 ola.c -o ola   # compila com avisos ligados
    ./ola                             # executa (no Windows: ola.exe)
    

O detalhe da instalação está em Ambiente e ferramentas. A flag -Wall liga os avisos do compilador — mantenha-a sempre; ela apontará problemas que, de outra forma, virariam bugs difíceis.

4. Variáveis e memória

4.1 A ideia central

Uma variável é um espaço nomeado na memória que guarda um valor que pode mudar ao longo da execução. Pense em uma variável como uma caixa etiquetada: a etiqueta é o nome (idade), o conteúdo é o valor (20), e o tamanho/formato da caixa é determinado pelo tipo (int).

flowchart LR
    subgraph ram["Memória RAM"]
    C1["idade<br/>┌────┐<br/>│ 20 │<br/>└────┘"]
    C2["altura<br/>┌──────┐<br/>│ 1.75 │<br/>└──────┘"]
    end

4.2 Bits, bytes e por que o tipo existe

No fundo, tudo na memória são bits (0/1). Um byte = 8 bits. O que dá significado a um punhado de bytes é o tipo: ele diz ao computador "interprete estes 4 bytes como um número inteiro" ou "interprete este 1 byte como um caractere". É por isso que, em C, toda variável precisa ter um tipo — sem ele, a mesma sequência de bits não teria sentido único.

O tipo determina três coisas: quanto espaço a variável ocupa, quais valores ela pode guardar e quais operações fazem sentido com ela.

4.3 Declaração e inicialização

Declarar uma variável é reservá-la (informando o tipo). Inicializar é dar-lhe um primeiro valor. Atribuir é (re)definir seu valor com o operador =.

int idade;          // declaração (sem valor definido ainda)
idade = 20;         // atribuição

double altura = 1.75;   // declaração + inicialização, tudo junto
char inicial = 'A';

Variável não inicializada contém lixo

Em C, uma variável declarada mas não inicializada contém um valor imprevisível (o que estava naquele pedaço de memória — o famoso "lixo de memória"). Nunca conte com um valor "zero" automático. Inicialize antes de usar:

int soma = 0;   // certo
int soma;       // perigoso se você usar "soma" antes de atribuir

Regras e bom senso para nomes de variáveis

  • Podem conter letras, dígitos e _, mas não podem começar com dígito.
  • Sem espaços e sem acentos (preço não; use preco).
  • Diferenciam maiúsculas de minúsculas: idade, Idade e IDADE são três variáveis distintas.
  • Não podem ser palavras reservadas (int, return, if, while, ...).
  • Escolha nomes que descrevem o conteúdo: media, totalAlunos, raio — e não x, xx, aux2. Código é lido muito mais vezes do que é escrito.

5. Tipos de dados fundamentais

Os tipos básicos ("primitivos") do C que usaremos no começo:

Tipo Guarda Tamanho típico* Faixa aproximada* Formato (printf/scanf)
int inteiros (positivos e negativos) 4 bytes −2.147.483.648 a 2.147.483.647 %d
float reais, precisão simples 4 bytes ~6–7 dígitos significativos %f
double reais, precisão dupla 8 bytes ~15–16 dígitos significativos %lf (scanf) / %f (printf)
char um caractere 1 byte 256 valores (ver abaixo) %c

* Tamanhos e faixas dependem do sistema/compilador; os valores acima são os típicos em computadores de 64 bits. Você pode conferir na sua máquina com sizeof (veja abaixo).

5.1 Inteiros (int) e a divisão inteira

int guarda números sem parte fracionária. Uma consequência importantíssima é a divisão inteira: quando os dois operandos são inteiros, o resultado é inteiro (a parte fracionária é descartada, não arredondada):

int a = 7, b = 2;
printf("%d\n", a / b);   // imprime 3  (não 3.5!)

Voltaremos a isso na seção de operadores — é uma das maiores fontes de bugs de iniciantes.

5.2 char: caractere é (também) um número

Um char guarda um caractere entre aspas simples: 'A', 'z', '?', '5'. Internamente, porém, ele guarda um número inteiro pequeno — o código do caractere segundo a tabela ASCII. Por exemplo, 'A' vale 65 e 'a' vale 97.

char letra = 'A';
printf("%c\n", letra);   // A
printf("%d\n", letra);   // 65  (o mesmo char, visto como número)
printf("%c\n", letra + 1); // B  (65 + 1 = 66 = 'B')

Curiosidade 💡 — 'A' × \"A\" × 65

  • 'A'um caractere (aspas simples), ocupa 1 byte.
  • "A" — uma cadeia de caracteres (aspas duplas): na verdade ocupa 2 bytes ('A' mais um marcador de fim). Cadeias (strings) são tema da Semana 08.
  • 65 — o número inteiro que, na tabela ASCII, corresponde a 'A'.

Confundir aspas simples com duplas é um erro clássico. Guarde: aspas simples para um caractere, aspas duplas para texto.

5.3 float × double: qual usar?

Ambos guardam números reais; a diferença é a precisão (quantos dígitos significativos são confiáveis). O double tem o dobro da precisão do float e é o padrão para cálculos na disciplina — use double a menos que haja um bom motivo para economizar memória. Números reais são escritos com ponto (não vírgula): 3.14, 1.75, -0.5.

Reais no computador são aproximações

Números reais são armazenados em ponto flutuante, um formato que representa a maioria dos valores de forma aproximada. Por isso, 0.1 + 0.2 pode não dar exatamente 0.3. Isso não é um "bug" do seu programa — é uma característica de como a máquina representa reais. A regra prática por ora: não compare reais com == esperando igualdade exata (voltaremos a isso quando fizer diferença).

5.4 Modificadores e sizeof

Existem variações dos tipos (que você encontrará ao longo do curso), como unsigned int (só não-negativos, o que dobra o maior valor positivo), long (inteiros maiores) e short. Você pode descobrir o tamanho de qualquer tipo com o operador sizeof:

printf("int    ocupa %zu bytes\n", sizeof(int));
printf("double ocupa %zu bytes\n", sizeof(double));
printf("char   ocupa %zu bytes\n", sizeof(char));

(O especificador %zu é o correto para o resultado de sizeof.)

5.5 Constantes com #define e const

Quando um valor não muda (π, a taxa de conversão, um limite), dê-lhe um nome. Isso deixa o código legível e fácil de manter:

#define PI 3.14159        // constante de pré-processador (sem ; e sem =)
const double TAXA = 5.25; // constante "de verdade" (tem tipo)

double area = PI * raio * raio;

Por convenção, nomes de constantes são escritos em MAIÚSCULAS.

6. Entrada e saída (E/S)

Um programa útil quase sempre recebe dados (entrada) e comunica resultados (saída). Em C, as ferramentas básicas são printf (saída) e scanf (entrada), ambas de <stdio.h>.

6.1 printf — imprimindo na tela

O printf recebe uma string de formato e, opcionalmente, valores para preencher os especificadores de formato (os %...), na ordem:

int idade = 20;
double altura = 1.75;
printf("Tenho %d anos e %.2f m de altura.\n", idade, altura);
// Saída: Tenho 20 anos e 1.75 m de altura.

Principais especificadores:

Especificador Serve para Exemplo de saída
%d inteiro (int) 42
%f real (float/double) 3.140000
%.2f real com 2 casas decimais 3.14
%c um caractere A
%s texto (string — Semana 08) Olá
%% um sinal de porcentagem literal %

Sequências de escape — caracteres especiais dentro das aspas, iniciados por \:

Escape Efeito
\n quebra de linha (nova linha)
\t tabulação (um "tab")
\\ uma barra invertida literal
\" aspas duplas dentro do texto
printf("Nome:\tAna\n");      // "Nome:" + tab + "Ana" + nova linha
printf("Ele disse \"oi\".\n");

Controlando a aparência dos números

  • %.2f fixa o número de casas decimais (útil para dinheiro: R$ %.2f).
  • %5d reserva uma largura mínima de 5 caracteres (alinha colunas).
  • Combine: %8.2f → largura 8, com 2 casas decimais.

6.2 scanf — lendo do teclado

O scanf lê valores digitados e os guarda em variáveis. A grande particularidade: é preciso passar o endereço da variável, usando o operador &:

int idade;
printf("Digite sua idade: ");
scanf("%d", &idade);        // lê um inteiro e guarda em "idade"

Por que o &? Porque o scanf precisa saber onde, na memória, depositar o valor lido — e &idade significa "o endereço da variável idade". Por enquanto, aceite como uma regra; o mecanismo por trás do & (endereços e ponteiros) é justamente um dos grandes temas da Unidade 3, e lá tudo isto fará total sentido.

Erro clássico: esquecer o & no scanf

scanf("%d", idade); (sem &) normalmente compila, mas provoca comportamento errado ou trava o programa. Para os tipos básicos (int, float, double, char), sempre use &: scanf("%d", &idade);.

Cuidado com o %lf no scanf de double

Na leitura de um double, use %lf; na impressão, %f já basta:

double x;
scanf("%lf", &x);      // leitura: %lf
printf("%f\n", x);     // impressão: %f

6.3 Um programa completo de E/S

reajuste.c
#include <stdio.h>

int main(void) {
    double salario, percentual;

    printf("Salario atual: ");
    scanf("%lf", &salario);
    printf("Percentual de reajuste (ex.: 10 para 10%%): ");
    scanf("%lf", &percentual);

    double novo = salario + salario * (percentual / 100.0);
    printf("Novo salario: R$ %.2f\n", novo);

    return 0;
}

Observe: o %% na string imprime um % literal; o / 100.0 (e não / 100) garante que a conta seja feita com números reais.

7. Operadores e expressões

Uma expressão combina valores, variáveis e operadores para produzir um novo valor. Dominar operadores é dominar o "cálculo" dos programas.

7.1 Operadores aritméticos

Operador Operação Exemplo Resultado
+ soma 3 + 4 7
- subtração 10 - 6 4
* multiplicação 3 * 4 12
/ divisão 7 / 2 3 (inteira!) ou 3.5
% resto da divisão (módulo) 17 % 5 2

A divisão / comporta-se de dois modos:

printf("%d\n",  7 / 2);     // 3    -> ambos int: divisão inteira
printf("%f\n",  7.0 / 2);   // 3.5  -> um deles real: divisão real
printf("%f\n",  7 / 2.0);   // 3.5

O módulo % devolve o resto e só funciona com inteiros. É extremamente útil:

17 % 5   // 2  (17 = 3*5 + 2)
10 % 2   // 0  -> número par tem resto 0 na divisão por 2
7 % 10   // 7  (7 dividido por 10 dá 0, resto 7)

Truques com % que você usará muito

  • Par ou ímpar? n % 2 == 0 → par.
  • Múltiplo de k? n % k == 0.
  • Último dígito de um número (na base 10): n % 10.

7.2 Precedência e associatividade

Assim como na matemática, os operadores têm ordem de avaliação. *, / e % têm precedência maior que + e -. Em caso de mesma precedência, a avaliação é da esquerda para a direita (associatividade à esquerda).

2 + 3 * 4       // 14, não 20  (multiplica antes)
(2 + 3) * 4     // 20          (parênteses forçam a ordem)
10 - 4 - 3      // 3           (avalia (10-4)-3)

Na dúvida, use parênteses

Ninguém precisa memorizar toda a tabela de precedência. Parênteses deixam a intenção explícita e o código mais legível. Prefira (a * b) + c a confiar na memória.

7.3 Atribuição e seus atalhos

O = atribui (não "é igual a"!). Existem atalhos para "operar e atribuir":

int x = 10;
x += 5;   // equivale a x = x + 5;   -> 15
x -= 3;   // x = x - 3;              -> 12
x *= 2;   // x = x * 2;              -> 24
x /= 4;   // x = x / 4;              -> 6
x %= 4;   // x = x % 4;              -> 2

7.4 Incremento e decremento

Somar ou subtrair 1 é tão comum que existe uma forma curta:

int i = 5;
i++;   // pós-incremento: i passa a valer 6 (equivale a i = i + 1)
i--;   // i volta a 5

Curiosidade 💡 — i++ × ++i

Existem duas formas: pós-fixada (i++) e pré-fixada (++i). Ambas somam 1 a i; a diferença aparece quando usadas dentro de uma expressão maior: ++i usa o valor já incrementado, i++ usa o valor antigo e só depois incrementa.

int a = 5, b;
b = a++;   // b = 5, depois a = 6
b = ++a;   // a = 7, depois b = 7
Usaremos muito o incremento nos laços da Semana 03. Por ora, quando estiver sozinho na linha, i++ e ++i fazem a mesma coisa.

7.5 Operadores relacionais

Comparam dois valores e produzem um resultado lógico (verdadeiro/falso):

Operador Significado Exemplo Resultado
== igual a 3 == 3 verdadeiro
!= diferente de 3 != 4 verdadeiro
< menor que 2 < 5 verdadeiro
> maior que 2 > 5 falso
<= menor ou igual 5 <= 5 verdadeiro
>= maior ou igual 4 >= 5 falso

= NÃO é == — o erro que todo mundo comete

  • x = 5 atribui 5 a x.
  • x == 5 pergunta se x vale 5.

Trocar um pelo outro dentro de um if (Semana 02) é uma fonte enorme de bugs — e, pior, costuma compilar sem erro. Fique atento(a).

7.6 Como C representa verdadeiro e falso

C não tinha, tradicionalmente, um tipo "booleano" separado. A convenção é:

  • falso é o valor 0;
  • verdadeiro é qualquer valor diferente de zero (por convenção, 1).

Uma comparação como 2 < 5 produz o inteiro 1; 2 > 5 produz 0:

printf("%d\n", 2 < 5);   // 1
printf("%d\n", 2 > 5);   // 0

7.7 Operadores lógicos e o "curto-circuito"

Combinam condições. Serão o coração das decisões (Semana 02):

Operador Nome Verdadeiro quando...
&& E (and) ambas as condições são verdadeiras
\|\| OU (or) pelo menos uma é verdadeira
! NÃO (not) inverte: verdadeiro vira falso e vice-versa
int idade = 20;
double altura = 1.60;

(idade >= 18) && (altura >= 1.50)   // verdadeiro (as duas valem)
(idade < 12) || (idade > 60)        // falso (nenhuma vale)
!(idade >= 18)                       // falso (nega o verdadeiro)

Curiosidade 💡 — avaliação em curto-circuito

O C é "preguiçoso" ao avaliar && e ||. No &&, se a primeira condição já é falsa, ele nem avalia a segunda (o resultado já será falso). No ||, se a primeira já é verdadeira, ele para. Isso, além de eficiente, permite proteções elegantes que você usará mais adiante (por exemplo, testar se um valor é válido antes de usá-lo).

7.8 Conversão de tipos (e o cast)

Quando uma expressão mistura tipos, o C faz conversões automáticas (um int "vira" double para poder ser somado a outro double, por exemplo). Às vezes você quer forçar uma conversão — isso se chama cast e se escreve com o tipo entre parênteses:

int total = 7, n = 2;
double media = total / n;            // 3.0  -> a divisão foi INTEIRA antes de virar double!
double certo = (double) total / n;   // 3.5  -> força total a double antes de dividir

O segundo caso é o correto: o (double) converte total para real antes da divisão, evitando a divisão inteira. Guarde este padrão — ele resolve um dos bugs mais frequentes em cálculos de médias.

8. Erros comuns desta semana (resumão)

Checklist de armadilhas

  • ; esquecido no fim da instrução (erro aparece na linha seguinte).
  • = (atribui) no lugar de == (compara).
  • & esquecido no scanf.
  • %lf na leitura de double (e não %f).
  • Divisão inteira indesejada (7 / 23) — use .0 ou cast.
  • Aspas simples 'A' (caractere) × aspas duplas "A" (texto).
  • Usar variável não inicializada (contém lixo).
  • Acento/espaço em nome de variável.

👥 Quarta — Encontro

Chegue ao encontro tendo estudado o material acima e tendo executado os exemplos. O encontro é o momento de consolidar e tirar dúvidas — não de ver o conteúdo pela primeira vez. Roteiro previsto:

  1. Revisão relâmpago dos conceitos-chave (compilação, variáveis/tipos, E/S, operadores).
  2. Construção ao vivo, do zero, de um programa completo, praticando a modelagem: ler o enunciado → identificar entrada, processamento e saída → codificar → testar.
  3. Galeria de erros: provocamos de propósito os erros da seção 8 para você aprender a ler as mensagens do compilador.

Problema-guia do encontro — conta de restaurante: ler o valor consumido e a quantidade de pessoas, calcular a taxa de serviço (10%) e dividir o total igualmente entre as pessoas.

restaurante.c
#include <stdio.h>

#define TAXA_SERVICO 0.10   // 10%

int main(void) {
    double consumo;
    int pessoas;

    printf("Valor consumido: ");
    scanf("%lf", &consumo);
    printf("Numero de pessoas: ");
    scanf("%d", &pessoas);

    double total = consumo + consumo * TAXA_SERVICO;
    double porPessoa = total / pessoas;   // pessoas é int, mas total é double -> divisão real

    printf("Total com servico: R$ %.2f\n", total);
    printf("Cada pessoa paga:  R$ %.2f\n", porPessoa);
    return 0;
}

Perguntas para pensar antes do encontro: por que porPessoa sai com casas decimais mesmo pessoas sendo int? O que aconteceria se trocássemos total por um int?


✍️ Sexta — Estudo dirigido

Reserve este tempo para praticar de verdade. O objetivo não é "ver a resposta", e sim escrever, errar, corrigir e executar.

Exercícios guiados (Beecrowd)

Crie sua conta no Beecrowd e resolva, em C, a trilha inicial. Sugestão de ordem (dificuldade crescente):

Problema O que exercita
1000 Hello World! primeiro programa, printf
1001 Extremamente Básico ler 2 int, somar
1002 Área do Círculo double, %.4f, constante PI
1003 / 1004 Soma / Produto Simples E/S básica
1006 Média 1 média com double
1007 Diferença expressões com * e -
1010 Cálculo Simples E/S + multiplicação + formatação
1011 Esfera fórmula com double e constante
1013 O Maior expressão aritmética "esperta"

Desafios para escrever do zero

  1. Trocador de moedas: ler um valor em reais e a cotação do dólar; imprimir o equivalente em dólares com 2 casas decimais.
  2. Conversão de temperatura: ler Celsius e imprimir Fahrenheit (F = C * 9 / 5 + 32). Atenção: onde a divisão inteira pode te sabotar? Corrija com 9.0.
  3. Decompondo o tempo: ler uma duração total em segundos e imprimir quantas horas, minutos e segundos ela representa. (Dica: use / e %.)
  4. Último dígito: ler um inteiro e imprimir apenas o seu último dígito. (Dica: % 10.)
  5. Média ponderada: ler três notas e três pesos e calcular a média ponderada com 2 casas decimais.
  6. Explorando sizeof: escreva um programa que imprime o tamanho, em bytes, de int, char, float e double na sua máquina e compare com a tabela da seção 5.

Para investigar (curiosidade prática)

  • Rode printf("%d\n", 'A'); e explique o resultado.
  • Rode printf("%f\n", 0.1 + 0.2); com muitas casas (%.17f). O que você observa? Relacione com a seção 5.3.

✅ Checklist de autoavaliação

Marque com sinceridade — se algum item não estiver ✅, volte à seção correspondente.

  • Explico, com minhas palavras, o caminho código → compilador → executável.
  • Sei o que faz cada linha do "Olá, mundo" e por que main e return 0 existem.
  • Entendo o que é uma variável e por que toda variável em C tem um tipo.
  • Sei declarar e inicializar int, double e char, e sei que não inicializar é perigoso.
  • Uso os especificadores certos: %d, %f/%lf, %c; e sei formatar com %.2f.
  • Leio dados com scanf lembrando do & e do %lf para double.
  • Prevejo o resultado de uma expressão, incluindo divisão inteira, %, precedência e conversão de tipos.
  • Não confundo = com ==, nem 'A' com "A".

🔗 Referências e para se aprofundar

  • Material 2026.1 — Aula 01: Primeiros Passos com Programação em C.
  • BACKES, André. Linguagem C: completa e descomplicada. (capítulos iniciais: introdução, variáveis, tipos, E/S e operadores.)
  • KERNIGHAN, B.; RITCHIE, D. The C Programming Language (o clássico "K&R"), cap. 1–2.
  • MIZRAHI, Victorine V. Treinamento em Linguagem C.
  • Documentação de referência: cppreference — C (avançado, bom para consultar detalhes).
  • Prática: Beecrowd · Tabela ASCII: procure "tabela ASCII".

Antes de seguir para a Semana 02

Não avance sem ter digitado e executado ao menos os exemplos e uns 3–4 exercícios. O conteúdo desta semana é a base de tudo o que vem depois — condicionais, laços, funções, ponteiros. Tempo investido aqui rende juros o semestre inteiro.