O Laço For: Um Guia Visual e Prático
Aprenda o laço for de forma visual: as três partes e a ordem em que rodam, padrões de contagem, o problema da cerca, laços aninhados, o for baseado em intervalo, armadilhas comuns, medições reais (47× só pela ordem dos laços) e exercícios com respostas.

Nesta página
Precisa imprimir uma tabuada, somar cem números ou visitar cada pixel de uma foto? Quando você sabe quantas vezes algo deve se repetir, o laço for é a ferramenta certa. Ele é o laço mais comum em C, C++, Java, C#, JavaScript e em muitas linguagens parecidas.
Neste guia você vai desmontar um laço for, vê-lo rodar passo a passo, aprender os padrões de contagem que todo mundo usa, resolver o famoso problema da cerca, montar laços aninhados e uma tabuada e ver uma medição em que só trocar dois laços de lugar deixou um programa 47 vezes mais lento. Exercícios com respostas fecham o artigo.
Três partes numa linha só
Um laço for junta tudo o que controla a repetição na primeira linha:
for (inicio; verificacao; passo) {
// corpo: roda de novo e de novo enquanto a verificação for verdadeira
}
Aqui está o exemplo clássico, contando de 1 a 10:
1#include <iostream>
2
3int main() {
4 for (int numero = 1; numero <= 10; numero++) {
5 std::cout << numero << " ";
6 }
7 std::cout << "\n";
8}Execução de exemplo:
1 2 3 4 5 6 7 8 9 10 Passo a passo
O que acontece exatamente, e em que ordem? Aqui está um laço mais curto, de 1 a 3, acompanhado uma ação por vez:

Duas coisas para reparar: a verificação roda uma vez a mais que o corpo (a última verificação é a que diz "pare"), e quando o laço termina, numero já passou um além do fim.
Um laço for é um while disfarçado
Todo laço for pode ser reescrito como um laço while, e vice-versa. O laço for só mantém as três partes juntas, e aí fica difícil esquecer uma delas:

Padrões de contagem
O início, a verificação e o passo podem ser o que você quiser, e isso faz do laço for uma máquina de contar bem flexível:

1#include <iostream>
2
3int main() {
4 std::cout << "Regressiva: ";
5 for (int numero = 10; numero >= 1; numero--) std::cout << numero << " ";
6
7 std::cout << "\nPares: ";
8 for (int numero = 0; numero <= 20; numero += 2) std::cout << numero << " ";
9
10 std::cout << "\nDe 5 em 5: ";
11 for (int numero = 5; numero <= 50; numero += 5) std::cout << numero << " ";
12
13 std::cout << "\nPotências de dois: ";
14 for (int numero = 1; numero <= 1024; numero *= 2) std::cout << numero << " ";
15
16 std::cout << "\n";
17}1Regressiva: 10 9 8 7 6 5 4 3 2 1
2Pares: 0 2 4 6 8 10 12 14 16 18 20
3De 5 em 5: 5 10 15 20 25 30 35 40 45 50
4Potências de dois: 1 2 4 8 16 32 64 128 256 512 1024 Dá até para usar duas variáveis ao mesmo tempo, separadas por vírgulas. Aqui uma sobe enquanto a outra desce, até se encontrarem no meio:
1#include <iostream>
2
3int main() {
4 for (int esquerda = 0, direita = 9; esquerda < direita; esquerda++, direita--) {
5 std::cout << "(" << esquerda << ", " << direita << ") ";
6 }
7 std::cout << "\n";
8}(0, 9) (1, 8) (2, 7) (3, 6) (4, 5) Somando: o pequeno Gauss
Uma história clássica de sala de aula: um professor mandou a turma somar todos os números de 1 a 100, esperando que isso a mantivesse ocupada. O pequeno Carl Friedrich Gauss respondeu quase na hora. Um laço for faz isso do jeito paciente:
1#include <iostream>
2
3int main() {
4 int total = 0;
5 for (int numero = 1; numero <= 100; numero++) {
6 total += numero;
7 }
8 std::cout << "1 + 2 + ... + 100 = " << total << "\n";
9 std::cout << "O atalho de Gauss: 100 * 101 / 2 = " << 100 * 101 / 2 << "\n";
10}1 + 2 + ... + 100 = 5050
O atalho de Gauss: 100 * 101 / 2 = 5050O padrão total = 0 antes do laço e total += alguma coisa dentro dele se chama acumulador, e você vai usá-lo o tempo todo.
O problema da cerca
Aqui vai um quebra-cabeça que derruba programadores desde que existem programas. Você vai construir uma cerca de 10 metros, com um poste a cada metro. Quantos postes você precisa?

A maioria das pessoas diz 10. A resposta é 11: tem um poste no 0 m e um no 10 m.
1#include <iostream>
2
3int main() {
4 int postes = 0;
5 for (int metro = 0; metro <= 10; metro++) { // um poste em 0 m, 1 m, ..., 10 m
6 postes++;
7 }
8 std::cout << "Uma cerca de 10 m com um poste a cada metro precisa de " << postes << " postes\n";
9}Uma cerca de 10 m com um poste a cada metro precisa de 11 postesErrar por um desse jeito é tão comum que tem nome: erro por um (off-by-one error). Os dois estilos de laço que você mais vai usar:
for (int indice = 0; indice < quantidade; indice++)roda exatamentequantidadevezes, de 0 a quantidade − 1. É o padrão para arrays, que contam a partir do 0.for (int numero = 1; numero <= quantidade; numero++)também rodaquantidadevezes, de 1 a quantidade. É natural para a contagem "humana".
Misturar os dois (começar no 0 e usar <=) dá uma volta a mais.
Laços dentro de laços
O corpo de um laço for pode ter outro laço for. Aí o laço de dentro roda inteirinho a cada volta do laço de fora:

O programa clássico com laços aninhados é a tabuada:
1#include <iomanip>
2#include <iostream>
3
4int main() {
5 for (int linha = 1; linha <= 9; linha++) {
6 for (int coluna = 1; coluna <= 9; coluna++) {
7 std::cout << std::setw(3) << linha * coluna;
8 }
9 std::cout << "\n";
10 }
11}1 1 2 3 4 5 6 7 8 9
2 2 4 6 8 10 12 14 16 18
3 3 6 9 12 15 18 21 24 27
4 4 8 12 16 20 24 28 32 36
5 5 10 15 20 25 30 35 40 45
6 6 12 18 24 30 36 42 48 54
7 7 14 21 28 35 42 49 56 63
8 8 16 24 32 40 48 56 64 72
9 9 18 27 36 45 54 63 72 81O std::setw(3) completa cada número até 3 caracteres de largura, para as colunas ficarem alinhadas.
Os limites do laço de dentro podem depender do laço de fora. Aqui o laço de dentro imprime tantas estrelas quanto o número da linha atual:
1#include <iostream>
2
3int main() {
4 for (int linha = 1; linha <= 5; linha++) {
5 for (int estrela = 1; estrela <= linha; estrela++) {
6 std::cout << '*';
7 }
8 std::cout << "\n";
9 }
10}1*
2**
3***
4****
5*****Cada par, uma vez
Começar o laço de dentro em primeiro + 1 visita cada par de itens exatamente uma vez, sem repetições e sem juntar um item com ele mesmo. Veja quantos apertos de mão acontecem quando 5 pessoas se cumprimentam todas entre si:
1#include <iostream>
2
3int main() {
4 const int pessoas = 5;
5 int apertosDeMao = 0;
6 for (int primeira = 1; primeira <= pessoas; primeira++) {
7 for (int segunda = primeira + 1; segunda <= pessoas; segunda++) {
8 std::cout << primeira << "-" << segunda << " ";
9 apertosDeMao++;
10 }
11 }
12 std::cout << "\n" << pessoas << " pessoas dão " << apertosDeMao << " apertos de mão\n";
13}1-2 1-3 1-4 1-5 2-3 2-4 2-5 3-4 3-5 4-5
5 pessoas dão 10 apertos de mãoEsse padrão está em todo lugar: procurar duplicados numa lista, achar as duas cidades mais próximas, comparar cada jogador com todos os outros. Mas repare como o trabalho cresce quando a lista aumenta:

A ordem dos laços importa: uma surpresa de 47×
Laços aninhados sobre uma grade podem ir linha por linha (linhas por fora) ou coluna por coluna (colunas por fora). Os dois visitam cada casa uma vez e dão a mesma resposta. Então não deveria importar qual você escolhe… certo?
Medimos isso, somando uma grade de 4.096 × 4.096 números (64 MB) dos dois jeitos:

A única diferença entre os dois era qual linha for vinha primeiro:
1// Rápido: linha por linha
2for (int linha = 0; linha < tamanho; linha++)
3 for (int coluna = 0; coluna < tamanho; coluna++)
4 total += grade[linha][coluna];
5
6// 47× mais lento: coluna por coluna
7for (int coluna = 0; coluna < tamanho; coluna++)
8 for (int linha = 0; linha < tamanho; linha++)
9 total += grade[linha][coluna];O for baseado em intervalo (C++11)
Quando você só quer visitar cada elemento de uma coleção, o C++ moderno tem uma forma mais curta, o for baseado em intervalo (range-based for): "para cada coisa nesta coleção".
1#include <iostream>
2#include <string>
3#include <vector>
4
5int main() {
6 std::vector<std::string> frutas = {"uva", "manga", "caju", "acerola"};
7 for (const std::string& fruta : frutas) {
8 std::cout << fruta << " tem " << fruta.size() << " letras\n";
9 }
10
11 std::string palavra = "sol";
12 for (char letra : palavra) {
13 std::cout << "[" << letra << "]";
14 }
15 std::cout << "\n";
16}1uva tem 3 letras
2manga tem 5 letras
3caju tem 4 letras
4acerola tem 7 letras
5[s][o][l]Sem índice, sem tamanho, nada para errar por um. Funciona com arrays, vetores, textos e a maioria dos outros contêineres.
Cópia ou o elemento de verdade?
Tem um porém. Por padrão, a variável do laço é uma cópia de cada elemento. Para mudar os elementos em si, acrescente & e transforme-a numa referência:

1#include <iostream>
2#include <vector>
3
4int main() {
5 std::vector<int> precos = {10, 20, 30};
6
7 for (int preco : precos) {
8 preco *= 2; // dobra uma cópia; o vetor não muda
9 }
10 std::cout << "Depois do laço com cópia: ";
11 for (int preco : precos) std::cout << preco << " ";
12
13 for (int& preco : precos) {
14 preco *= 2; // & quer dizer "o elemento de verdade": o vetor muda
15 }
16 std::cout << "\nDepois do laço com referência: ";
17 for (int preco : precos) std::cout << preco << " ";
18 std::cout << "\n";
19}Depois do laço com cópia: 10 20 30
Depois do laço com referência: 20 40 60 | Você quer… | Escreva |
|---|---|
| Ler valores pequenos (números, caracteres) | for (int valor : valores) |
| Ler valores grandes (textos, objetos) sem copiar | for (const std::string& nome : nomes) |
| Mudar os elementos | for (int& valor : valores) |
| Saber a posição também | o clássico for (std::size_t indice = 0; indice < valores.size(); indice++) |
Três armadilhas

Armadilha 1: um ponto e vírgula perdido
1#include <iostream>
2
3int main() {
4 for (int numero = 1; numero <= 3; numero++);
5 {
6 std::cout << "Olá!\n";
7 }
8}Olá!O ; logo depois dos parênteses é uma instrução vazia, e ela é o corpo do laço. O laço gira três vezes sem fazer nada e depois o bloco entre chaves roda uma vez. O GCC (com -Wall) percebe:
1pontoevirgula.cpp: In function 'int main()':
2pontoevirgula.cpp:4:5: warning: this 'for' clause does not guard... [-Wmisleading-indentation]
3 4 | for (int numero = 1; numero <= 3; numero++);
4 | ^~~
5pontoevirgula.cpp:5:5: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'for'
6 5 | {
7 | ^("Esta cláusula for não protege esta instrução, mas ela está recuada de um jeito enganoso, como se estivesse protegida pelo for.")
Armadilha 2: contagem regressiva com unsigned
Um unsigned int não pode ser negativo. Tire 1 do 0 e ele dá a volta até o seu maior valor, 4.294.967.295. Então numero >= 0 é sempre verdadeiro, e este laço nunca acaba:
for (unsigned int numero = 3; numero >= 0; numero--) {
std::cout << numero << "\n";
}Com um limite de segurança para parar depois de 6 linhas, dá para ver acontecendo:
1#include <iostream>
2
3int main() {
4 int impressos = 0;
5 for (unsigned int numero = 3; numero >= 0 && impressos < 6; numero--) { // impressos < 6 é uma rede de proteção
6 std::cout << numero << "\n";
7 impressos++;
8 }
9}13
22
31
40
54294967295
64294967294O -Wextra do GCC avisa: comparison of unsigned expression in '>= 0' is always true ("comparar uma expressão unsigned com '>= 0' é sempre verdadeiro"). Para contar até 0 de trás para a frente, use um int comum.
Armadilha 3: usar a variável do laço depois
Uma variável declarada na linha do for só existe dentro do laço:
1#include <iostream>
2
3int main() {
4 for (int indice = 0; indice < 3; indice++) {
5 std::cout << indice << " ";
6 }
7 std::cout << indice << "\n"; // indice só existe dentro do laço
8}1escopo.cpp: In function 'int main()':
2escopo.cpp:7:18: error: 'indice' was not declared in this scope; did you mean 'inline'?
3 7 | std::cout << indice << "\n"; // indice só existe dentro do laço
4 | ^~~~~~
5 | inline("'indice' não foi declarado neste escopo; você quis dizer 'inline'?" O compilador tenta adivinhar o que você quis escrever, nem sempre com sucesso.) Na verdade, isso é uma vantagem: cada laço ganha a sua própria variável novinha, e as antigas não vazam para causar confusão. Se você realmente precisar do valor depois, declare a variável antes do laço.
A mesma ideia em outras linguagens
| Linguagem | Contar de 1 a 10 | Para cada item |
|---|---|---|
| C, C++, Java, C# | for (int numero = 1; numero <= 10; numero++) | for (int valor : valores) (C++, Java), foreach (var valor in valores) (C#) |
| JavaScript | for (let numero = 1; numero <= 10; numero++) | for (const valor of valores) |
| Python | for numero in range(1, 11): | for valor in valores: |
O Python nem tem o laço for de três partes. O range(1, 11) dele produz de 1 a 10: o fim fica de fora, igualzinho a < 11. Aqui está o começo da tabuada do 7 em Python e JavaScript:
for vezes in range(1, 4):
print(7 * vezes)for (let vezes = 1; vezes <= 3; vezes++) {
console.log(7 * vezes);
}Os dois imprimem 7, 14 e 21.
Hora de praticar
Tente fazer estes antes de espiar as respostas. Copie cada programa num arquivo, compile com g++ -std=c++20 -Wall programa.cpp e rode.
Exercício 1: Adivinhe a saída (aquecimento). O que isto imprime?
for (int numero = 1; numero < 10; numero += 3) {
std::cout << numero << " ";
}Exercício 2: Conte as voltas. Sem rodar, quantas vezes o corpo de cada laço roda?
for (int indice = 0; indice <= 5; indice++) { ... } // a
for (int indice = 5; indice > 0; indice--) { ... } // b
for (int indice = 1; indice < 100; indice *= 10) { ... } // cExercício 3: Some os pares. Some todos os números pares de 1 a 100. (Dica: deixe o passo pular os ímpares.)
Exercício 4: Fatoriais. 5! ("5 fatorial") quer dizer 1 × 2 × 3 × 4 × 5 = 120. Imprima todos os fatoriais de 1! até 10!. (Dica: cresce rápido; use long long.)
Exercício 5: A tabuada do 7. Imprima de 7 x 1 = 7 até 7 x 10 = 70.
Exercício 6: Caçador de primos (desafio). Imprima todos os números primos até 50. Um primo não tem divisores além de 1 e dele mesmo. Use um laço aninhado para testar os divisores e break assim que achar um.
Quiz rápido
- Em que ordem rodam o início, a verificação, o corpo e o passo?
- Quantas vezes
for (int indice = 0; indice < 8; indice++)roda? Qual é o último valor deindicedentro do corpo? - O que há de errado com
for (int indice = 0; indice < 5; indice++);? - Dois laços aninhados rodam 100 vezes cada um. Quantas vezes o corpo de dentro roda?
- Em
for (int valor : valores),valor *= 2mudavalores?
Respostas
Exercício 1: 1 4 7. Depois do 7, o passo faz virar 10, e 10 < 10 é falso.
1 4 7 Exercício 2: (a) 6 vezes: 0, 1, 2, 3, 4, 5 (o clássico erro por um; o <= inclui o 5). (b) 5 vezes: 5, 4, 3, 2, 1. (c) 2 vezes: 1 e 10; o próximo valor, 100, falha no < 100.
Exercício 3:
1#include <iostream>
2
3int main() {
4 int total = 0;
5 for (int numero = 2; numero <= 100; numero += 2) {
6 total += numero;
7 }
8 std::cout << "Soma dos números pares de 1 a 100: " << total << "\n";
9}Soma dos números pares de 1 a 100: 2550Exercício 4: Um acumulador de novo, mas multiplicando em vez de somar, então ele começa em 1, não em 0.
1#include <iostream>
2
3int main() {
4 long long fatorial = 1;
5 for (int numero = 1; numero <= 10; numero++) {
6 fatorial *= numero;
7 std::cout << numero << "! = " << fatorial << "\n";
8 }
9}11! = 1
22! = 2
33! = 6
44! = 24
55! = 120
66! = 720
77! = 5040
88! = 40320
99! = 362880
1010! = 3628800Exercício 5:
1#include <iostream>
2
3int main() {
4 for (int vezes = 1; vezes <= 10; vezes++) {
5 std::cout << "7 x " << vezes << " = " << 7 * vezes << "\n";
6 }
7}17 x 1 = 7
27 x 2 = 14
37 x 3 = 21
47 x 4 = 28
57 x 5 = 35
67 x 6 = 42
77 x 7 = 49
87 x 8 = 56
97 x 9 = 63
107 x 10 = 70Exercício 6: O laço de dentro só precisa testar divisores até a raiz quadrada (divisor * divisor <= candidato): se um número tem um divisor maior que isso, ele também tem um menor.
1#include <iostream>
2
3int main() {
4 for (int candidato = 2; candidato <= 50; candidato++) {
5 bool ehPrimo = true;
6 for (int divisor = 2; divisor * divisor <= candidato; divisor++) {
7 if (candidato % divisor == 0) {
8 ehPrimo = false;
9 break; // um divisor basta para descartá-lo
10 }
11 }
12 if (ehPrimo) std::cout << candidato << " ";
13 }
14 std::cout << "\n";
15}2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 Quiz: (1) O início uma vez; depois verificação, corpo, passo, verificação, corpo, passo… até a verificação ser falsa. (2) 8 vezes; o último valor dentro do corpo é 7. (3) O ponto e vírgula: ele vira o corpo inteiro (vazio) do laço, então o bloco depois dele roda uma vez só. (4) 100 × 100 = 10.000 vezes. (5) Não: valor é uma cópia. Use int& valor para mudar os elementos.
Cola rápida
| Eu quero… | Escreva |
|---|---|
| Contar de 1 a 10 | for (int numero = 1; numero <= 10; numero++) |
Repetir exatamente quantidade vezes | for (int indice = 0; indice < quantidade; indice++) |
| Contagem regressiva | for (int numero = 10; numero >= 1; numero--) |
| Contar de 2 em 2, de 5 em 5… | for (int numero = 0; numero <= 100; numero += 5) |
| Visitar cada elemento | for (int valor : valores) |
| Mudar cada elemento | for (int& valor : valores) |
| Percorrer uma grade (na ordem rápida) | for (linha…) { for (coluna…) { grade[linha][coluna] } } |
| Visitar cada par uma vez | for (primeiro…) { for (segundo = primeiro + 1…) { … } } |
| Somar coisas | int total = 0; for (…) { total += …; } |
| Sair mais cedo / pular uma volta | break; / continue; |
Resumindo
O laço for é o laço certo quando você sabe quantas vezes vai repetir:
- Três partes numa linha: o início roda uma vez; a verificação roda antes de cada volta; o passo roda depois de cada volta.
- Mude as partes, mude o padrão: contar de trás para a frente, de 2 em 2, dobrando, ou com duas variáveis ao mesmo tempo.
- Cuidado com os postes:
indice < quantidadea partir do 0 enumero <= quantidadea partir do 1 rodamquantidadevezes; misturar os dois dá uma volta a mais. - Laços aninhados multiplicam: 3 × 4 = 12 visitas; todos os pares de 10.000 itens dão uns 50 milhões de comparações.
- A ordem importa: linha por linha foi 47 vezes mais rápido que coluna por coluna no nosso teste.
- O for baseado em intervalo visita cada elemento sem índice para errar; acrescente
¶ mudar os elementos.
Para ver quando usar o while, leia Os Laços While e Do-While; para tomar decisões dentro dos seus laços, O Comando If; e para usar laços com dados de verdade, Arrays em C++.
Leia a seguir

O Que É a Linguagem de Programação Rust? Um Guia Simples da Linguagem Rápida Que Não Deixa Você Travar
Um guia simples e sem jargões sobre o Rust, a linguagem tão rápida quanto o C que impede famílias inteiras de erros de memória antes de o programa rodar. Entenda a ideia de posse, por que gigantes da tecnologia o adotam e onde ele é usado.

O Que É a Linguagem de Programação Go? Um Guia Simples da Linguagem da Nuvem
Um guia simples e sem jargões sobre o Go, a linguagem simples e rápida que o Google criou para a nuvem. Entenda o que são goroutines, por que um programa Go é um arquivo só e como o Go passou a mover o Docker, o Kubernetes e boa parte da internet.

O Que É a Linguagem de Programação Ruby? Um Guia Simples da Linguagem Feita para a Felicidade
Um guia simples e sem jargões sobre o Ruby, a linguagem de programação feita para deixar os programadores felizes. Entenda por que o código Ruby parece inglês, como o Ruby on Rails move sites como GitHub e Shopify, e onde o Ruby brilha.
Comentários
Seja gentil e específico. Comentários com links de contas novas aparecem depois da análise de um moderador.