Trilha de aprendizado · Nível 9 · Tutorial 9

Vetores de tamanho fixo e índices seguros

Armazene e percorra pequenas sequências em vetores de tamanho fixo, conferindo índices, inicialização e consumo de memória.

  • Nível: Iniciante
  • Duração: 20 min
  • 8 passos
Vetores de tamanho fixo e índices seguros

O que você vai percorrer

  1. Declare e inicialize uma sequência Declare sequências fixas e preveja seus valores após diferentes formas de inicialização. 3 min
  2. Leia e altere a posição certa Use índices iniciados em zero para ler e atualizar exatamente a posição desejada de um vetor. 3 min
  3. Reconheça acessos fora do vetor Analise limites de vetores e reconheça por que acessos fora da faixa não têm resultado previsível. 2 min
  4. Valide antes de acessar Construa uma condição que libera leituras e escritas apenas para índices dentro da faixa do vetor. 3 min
  5. Percorra sem ultrapassar o limite Use um laço for com limite exclusivo para visitar cada elemento de um vetor de tamanho fixo exatamente uma vez. 3 min
  6. Calcule o espaço ocupado Estime a memória reservada pelos elementos de vetores e compare escolhas de tipo e quantidade no Arduino Uno R3. 2 min
  7. Rastreie índices e alterações Registre condições, leituras e atualizações para identificar exatamente os acessos feitos e o estado final de um vetor. 3 min
  8. Aplicação final: confira um vetor seguro 3 min

O que você vai aprender

  • Declarar e inicializar um vetor com quantidade e tipo adequados.
  • Ler e atualizar elementos por índices válidos.
  • Percorrer todos os elementos sem acessar uma posição além do vetor.
  • Estimar a memória ocupada pelos elementos declarados.
  • Rastrear acessos e identificar por análise índices negativos ou maiores que o permitido.

Antes de começar

  • Funções com parâmetros e retorno
  • Repetições com while e for
  • Variáveis e tipos no firmware

Passo 1 de 8

Declare e inicialize uma sequência

Declare sequências fixas e preveja seus valores após diferentes formas de inicialização.

O que um vetor reserva

Uma sequência em células

Um vetor de tamanho fixo agrupa uma quantidade definida de elementos do mesmo tipo. Pense em uma faixa de células vizinhas na memória: a declaração reserva todas elas de uma vez.

A quantidade faz parte da declaração. Já os números guardados nas células são os valores e podem ser definidos na inicialização. Ter tamanho fixo não torna esses valores permanentes; eles poderão mudar mais adiante.

Quantidade e valores

Diagrama de quatro células consecutivas com os valores 12, 25, 8 e 40; a quantidade é quatro.

A quantidade é 4; os valores armazenados são 12, 25, 8 e 40.

Declare e inicialize

Declaração com lista

No Arduino, use uma constante inteira positiva para registrar a quantidade. Ela precisa ser conhecida na compilação. Em seguida, declare o tipo dos elementos, o nome do vetor e a quantidade entre colchetes.

A lista entre chaves inicializa as células na ordem em que os valores aparecem. Escolha valores que caibam no tipo: uint8_t, por exemplo, comporta valores de 0 a 255.

Um vetor de leituras

Declaração de uma sequência com quatro valores.

cpp
const uint8_t QUANTIDADE = 4;

uint8_t leituras[QUANTIDADE] = {12, 25, 8, 40};

Exemplo

Leia o código

A declaração reserva exatamente quatro elementos uint8_t. A lista também tem quatro valores, portanto cada célula recebe um valor explícito.

Quando faltam valores

Listas completas, parciais e vazias

A lista pode ter menos valores que a quantidade. Nesse caso, os elementos restantes são inicializados com zero. Uma lista vazia zera todos os elementos.

Já uma lista com mais valores que a quantidade não cabe no vetor e produz erro de compilação. Não tente usar um vetor como se tivesse mais células do que foi declarado.

Três inicializações válidas

Compare os valores resultantes de cada inicialização válida.

cpp
const uint8_t QUANTIDADE = 4;

uint8_t completo[QUANTIDADE] = {7, 9, 2, 5};
// Resultado: 7, 9, 2, 5

uint8_t parcial[QUANTIDADE] = {7, 9};
// Resultado: 7, 9, 0, 0

uint8_t zerado[QUANTIDADE] = {};
// Resultado: 0, 0, 0, 0

Atenção

Atenção

Evite declarar um vetor local automático sem uma lista e depois supor que ele começa em zero. Sem inicialização explícita, seus valores não devem ser lidos como valores conhecidos.

Pratique a declaração

Confira a inicialização

Associe cada lista ao conteúdo que ela produz em um vetor uint8_t com quantidade 4.

Faça as associações.

Toque em um item e depois no par correspondente.

Complete a declaração

Complete a declaração de um vetor com quatro valores inteiros sem sinal de 8 bits.

cpp
const uint8_t QUANTIDADE = 4;

 amostras[] = {10, 20, 30, 40};

Passo 2 de 8

Leia e altere a posição certa

Use índices iniciados em zero para ler e atualizar exatamente a posição desejada de um vetor.

Localize cada elemento

Quantidade, posição e valor

Um vetor com N elementos usa índices que começam em zero. Portanto, os índices válidos vão de 0 até N - 1.

Exemplo: se leituras tem 4 elementos, sua quantidade é 4, mas o último índice é 3.

  • quantidade: 4
  • primeiro índice: 0
  • último índice: 3

O número entre colchetes indica a posição; o conteúdo guardado nela é o valor.

Diagrama de um vetor com quatro células: os índices acima são 0, 1, 2 e 3; os valores nas células são 12, 25, 18 e 30.

Índices identificam posições; valores são os conteúdos dessas posições.

Leia e atualize com colchetes

Leia usando o índice

Use colchetes para acessar uma posição específica do vetor. A expressão leituras[1] lê o valor que está na posição de índice 1.

Com o vetor abaixo, essa leitura produz 25. Ela não significa “o primeiro elemento”: o primeiro está no índice 0.

Código para estudar

cpp
const int QUANTIDADE = 4;
int leituras[QUANTIDADE] = {12, 25, 18, 30};

int segundaLeitura = leituras[1];  // recebe 25

Exemplo

Atualize só a posição indicada

A atribuição também pode usar colchetes. Nesta instrução, apenas a célula de índice 2 recebe outro valor:

leituras[2] = 40;

Antes: {12, 25, 18, 30}

Depois: {12, 25, 40, 30}

Os valores nos índices 0, 1 e 3 permanecem iguais.

Comparação entre o vetor antes e depois de atualizar o índice 2, que muda de 18 para 40.

Uma atualização direcionada altera o conteúdo de uma única posição.

Confira seu acesso

Pratique: escolha as posições certas

Complete os índices para que valorLido receba 25 e para que o valor 18 seja substituído por 40.

cpp
int leituras[4] = {12, 25, 18, 30};

int valorLido = leituras[];
leituras[] = 40;

Passo 3 de 8

Reconheça acessos fora do vetor

Analise limites de vetores e reconheça por que acessos fora da faixa não têm resultado previsível.

Veja onde a faixa termina

O limite não é conferido automaticamente

Em C/C++, um vetor comum não confere sozinho se o número entre colchetes aponta para uma posição existente. O compilador pode aceitar um acesso mesmo quando ele está fora dos limites.

Para const int N = 4, existem quatro elementos, mas somente estes índices são válidos: 0, 1, 2 e 3. Portanto, N é a quantidade; não é um índice que possa ser usado para acessar o último elemento.

Diagrama de um vetor com quatro células. Os índices 0 a 3 estão dentro da faixa; -1, 4 e 5 apontam para fora.

Com quantidade 4, a faixa de índices é de 0 até 3.

Atenção

Atenção

Não experimente acessos inválidos para “ver o que acontece”. A forma segura de analisá-los aqui é comparar o índice com a faixa permitida, sem executar a linha problemática.

Não há valor confiável para prever

A aparência do código pode enganar

Considere que N vale 4. Analise cada linha, mas não a execute se o índice estiver fora da faixa.

cpp
const int N = 4;
int leitura[N] = {12, 25, 18, 30};

int a = leitura[3];   // dentro da faixa
int b = leitura[4];   // fora da faixa
leitura[-1] = 99;     // fora da faixa

Fora da faixa não tem resultado garantido

leitura[4] não se torna automaticamente zero. leitura[-1] não precisa gerar uma mensagem visível. Ler ou escrever fora da faixa tem comportamento não definido: a linguagem não fornece resultado confiável para prever.

O sketch pode compilar e até parecer funcionar em um teste. Isso não transforma o acesso em correto: em outra compilação, em outro momento ou após outra mudança no programa, o efeito pode ser diferente.

Atenção

Não confunda compilação com segurança

Um acesso fora da faixa pode causar dados incorretos, alterar outra informação ou não mostrar efeito perceptível. Nenhuma dessas possibilidades deve ser usada como expectativa do programa.

Prática: encontre os limites

Classifique os acessos

Para const int N = 4, classifique cada acesso.

Toque em um item e depois no par correspondente.

Verifique seu raciocínio

Compilei; então está certo?

Se dados[4] em um vetor de quatro elementos compila e o programa parece rodar normalmente, então esse acesso é seguro.

Ajuste o acesso ao último elemento

Complete com um índice literal válido para ler o último elemento de dados.

cpp
const int N = 4;
int dados[N] = {12, 25, 18, 30};
int ultimo = dados[];

Passo 4 de 8

Valide antes de acessar

Construa uma condição que libera leituras e escritas apenas para índices dentro da faixa do vetor.

Defina a porta de entrada

A faixa que libera o acesso

Antes de usar leituras[indice], verifique se indice está dentro da faixa válida. Para um vetor com QUANTIDADE elementos, a condição segura é:

indice >= 0 && indice < QUANTIDADE

O limite inferior inclui o zero. O superior exclui QUANTIDADE: se há 4 elementos, os índices aceitos são 0, 1, 2 e 3.

Use um tipo com sinal, como int, quando o índice puder vir de um cálculo ou de outra variável. Assim, um valor negativo pode ser representado e rejeitado pela primeira comparação.

Fluxo de validação

Diagrama de um vetor com quatro posições, mostrando que índices de 0 a 3 são permitidos e que -1 e 4 são bloqueados.

Valide a faixa antes dos colchetes: somente o ramo permitido alcança o vetor.

Dica

Tipos compatíveis

Não tente “consertar” um índice inválido convertendo-o para um tipo sem sinal. Por exemplo, converter -1 para unsigned int não o transforma no índice zero; produz outro valor, geralmente muito grande. Mantenha indice e QUANTIDADE como int neste exemplo, compare-os e só então acesse o vetor.

Deixe os colchetes no ramo seguro

Proteja o acesso

A leitura ou escrita deve ficar inteiramente dentro do bloco do if. No else, o programa apenas trata a rejeição: não consulta nem modifica nenhuma posição do vetor.

Atualização somente na faixa válida

Exemplo de atualização protegida

cpp
const int QUANTIDADE = 4;
int leituras[QUANTIDADE] = {10, 20, 30, 40};
int indice = -1;

if (indice >= 0 && indice < QUANTIDADE) {
  leituras[indice] = 99;
} else {
  // Índice rejeitado: o vetor permanece inalterado.
}

Exemplo

Casos de fronteira

Com QUANTIDADE = 4, analise a condição antes de considerar os colchetes:

• indice = -1: rejeitado; vetor intacto.
• indice = 0: aceito; altera a primeira posição.
• indice = 3: aceito; altera a última posição.
• indice = 4: rejeitado; vetor intacto.

Uma compilação sem erros não substitui essa análise da faixa.

Teste os limites

Pratique a proteção

Complete a condição que permite atualizar somente uma posição existente. Ela deve rejeitar tanto índices negativos quanto o índice igual à quantidade.

Complete a condição

Preencha os operadores de comparação da validação.

cpp
const int QUANTIDADE = 4;
int valores[QUANTIDADE] = {5, 6, 7, 8};
int indice = 4;

if (indice  0 && indice  QUANTIDADE) {
  valores[indice] = 50;
} else {
  // Nenhum elemento é acessado aqui.
}

Passo 5 de 8

Percorra sem ultrapassar o limite

Use um laço for com limite exclusivo para visitar cada elemento de um vetor de tamanho fixo exatamente uma vez.

Use a quantidade como fronteira

Um limite exclusivo

Para percorrer um vetor inteiro, comece no índice 0 e continue apenas enquanto o índice for menor que a quantidade.

Se QUANTIDADE vale 4, o laço usa os índices 0, 1, 2 e 3. Cada iteração corresponde a uma posição do vetor e a acessa uma única vez.

A constante usada na declaração também deve ser usada no limite do for. Assim, se a quantidade mudar, a declaração e o percurso continuam coerentes.

Do primeiro índice ao teste final

Diagrama de um vetor com quatro células: os índices 0 a 3 são visitados, e o índice 4 é barrado antes de acessar uma célula.

O índice chega a QUANTIDADE somente para encerrar o laço; ele não é usado no corpo.

Entenda a última iteração

Um percurso simples

Neste exemplo, a mesma constante define quantos elementos existem e até onde o laço pode ir. O corpo aumenta cada valor uma vez.

Atualize todos os elementos

Trecho para estudar ou incluir em um sketch Arduino.

cpp
const uint8_t QUANTIDADE = 4;
uint8_t niveis[QUANTIDADE] = {10, 20, 30, 40};

void setup() {
  for (uint8_t indice = 0; indice < QUANTIDADE; indice++) {
    niveis[indice] += 1;
  }
}

void loop() {
}

Rastreamento do limite

A condição é avaliada antes de cada execução do corpo. Veja a correspondência entre contador e posição acessada.

Quando `indice` se torna 4, a condição falha e não há acesso a `niveis[4]`.
Valor de indiceindice < QUANTIDADEAção
0verdadeiroacessa niveis[0]
1verdadeiroacessa niveis[1]
2verdadeiroacessa niveis[2]
3verdadeiroacessa niveis[3]
4falsoencerra; não acessa o vetor

Pratique o limite exclusivo

Complete o for seguro

Complete o percurso para atualizar todos os elementos de niveis exatamente uma vez.

cpp
for (uint8_t indice = ; indice  QUANTIDADE; indice++) {
  niveis[] += 1;
}

Teste final sem acesso

Depois de visitar a última posição válida, o índice vale __ no teste que encerra o laço.

Passo 6 de 8

Calcule o espaço ocupado

Estime a memória reservada pelos elementos de vetores e compare escolhas de tipo e quantidade no Arduino Uno R3.

Meça os elementos

A conta básica

Cada elemento de um vetor ocupa espaço na SRAM. Para estimar apenas o espaço dos elementos, use:

bytes do vetor = quantidade de elementos × bytes de cada elemento

Exemplo: um vetor com 10 valores uint8_t ocupa 10 × 1, ou seja, 10 bytes.

O vetor reserva esse espaço inteiro quando é declarado. Não importa se alguns elementos ainda valem 0 ou se você pretende usar somente parte deles depois.

Quantidade vezes tamanho

Diagrama de um vetor com oito células, relacionando a quantidade de elementos ao espaço reservado na memória.

A quantidade declarada determina quantas células do tipo escolhido serão reservadas.

Referência do Uno R3

No Arduino Uno R3 com ATmega328P, use estes tamanhos como referência para os exemplos deste tutorial. Eles pertencem a essa arquitetura; não suponha os mesmos valores em toda placa ou computador.

Tamanhos de tipos inteiros no Uno R3.

Bytes ocupados por um elemento de cada tipo no Uno R3.
TipoBytes por elementoFaixa aproximada
uint8_t10 a 255
int8_t1-128 a 127
int / unsigned int216 bits
int16_t / uint16_t216 bits
long / unsigned long432 bits
int32_t / uint32_t432 bits

Compare escolhas com cuidado

Escolha tipo e quantidade

Compare declarações considerando duas coisas: a faixa de valores necessária e a quantidade de posições.

Se cada leitura cabe entre 0 e 255, uint8_t é adequado. Para 100 leituras, ele reserva 100 bytes. Usar int para os mesmos valores reserva 200 bytes no Uno R3.

Escolher um tipo menor só é correto se todos os valores possíveis couberem nele. Economia de memória não justifica perder valores por uma escolha inadequada.

Mesmo número de posições, tipos diferentes

Duas declarações para comparar

cpp
const int AMOSTRAS = 100;

uint8_t leituras8[AMOSTRAS] = {};
int leiturasInt[AMOSTRAS] = {};

Exemplo

Resultado da comparação

  • leituras8: 100 × 1 = 100 bytes
  • leiturasInt: 100 × 2 = 200 bytes

As chaves vazias inicializam todos os elementos com zero, mas não reduzem o espaço reservado. Cada declaração continua tendo 100 elementos.

Atenção

Atenção ao total disponível

Um Uno R3 possui 2048 bytes de SRAM no ATmega328P. Essa SRAM também é usada por outras variáveis e pelas necessidades de execução do programa.

Portanto, calcular os bytes de um vetor responde: “quanto os elementos deste vetor reservam?”. Isso não revela o consumo total de SRAM do sketch nem quanto espaço livre resta.

Pratique o cálculo

Calcule a reserva

Complete o cálculo: uint16_t medidas[12] = {}; reserva ___ bytes para seus elementos no Uno R3.

Compare as declarações

Qual afirmação está correta no Uno R3?

Guarde esta regra

Em resumo

Para estimar o espaço dos elementos de um vetor no Uno R3:

  1. Conte as posições declaradas.
  2. Identifique os bytes do tipo nesta arquitetura.
  3. Multiplique quantidade × bytes por elemento.
  4. Confirme que o tipo comporta todos os valores previstos.

Inicializar com zero, ou ainda não usar certas posições, não diminui a reserva. E a reserva de um vetor é apenas uma parte da SRAM total usada pelo programa.

Passo 7 de 8

Rastreie índices e alterações

Registre condições, leituras e atualizações para identificar exatamente os acessos feitos e o estado final de um vetor.

O que registrar em um rastreamento

Acompanhe cada etapa

Um rastreamento simula a ordem do código sem executar acessos fora da faixa. Para cada etapa, registre o índice disponível, o resultado da condição, o elemento acessado e os valores antes e depois.

Uma etapa de leitura consulta um valor, então anterior e posterior são iguais. Uma etapa de atualização pode mudar o valor posterior. Se uma validação falhar ou o teste do laço encerrar o percurso, registre nenhum acesso: não há elemento, valor anterior nem valor posterior a anotar.

Índice, alteração e limite

Diagrama de um vetor com índices 0, 1 e 2; a célula de índice 1 muda de 7 para 10 e uma seta é interrompida antes de uma quarta posição inexistente.

O índice identifica a célula. Uma condição falsa impede o acesso antes dos colchetes.

Analise o fluxo antes de registrar

Atualização, rejeição e leituras

Código para analisar, sem executar acessos inválidos

cpp
const int QUANTIDADE = 3;
int niveis[QUANTIDADE] = {4, 7, 2};

int indiceParaAtualizar = 1;
if (indiceParaAtualizar >= 0 && indiceParaAtualizar < QUANTIDADE) {
  niveis[indiceParaAtualizar] += 3;
}

int indiceRejeitado = 3;
if (indiceRejeitado >= 0 && indiceRejeitado < QUANTIDADE) {
  niveis[indiceRejeitado] = 99;
}

for (int i = 0; i < QUANTIDADE; i++) {
  int leitura = niveis[i];
}

Ordem que o rastreamento deve seguir

A primeira condição aceita o índice 1 e altera somente niveis[1], de 7 para 10. A segunda condição rejeita o índice 3: como QUANTIDADE vale 3, os índices existentes são somente 0, 1 e 2. Logo, o corpo desse if não é executado.

No for, cada etapa apenas lê um elemento. Quando i chega a 3, o teste i < QUANTIDADE é falso; não existe leitura de niveis[3].

Colunas do registro

Use esta estrutura para organizar as etapas. A atividade da próxima tela completa os campos que ainda faltam.

“Nenhum” é um resultado importante: ele mostra que a proteção evitou o acesso.
EtapaÍndiceCondiçãoAcessoAnteriorPosterior
Atualização válida1verdadeiraniveis[1]710
Validação rejeitada3falsanenhum——
Leitura no laço0verdadeiraniveis[0]44
Teste final do laço3falsanenhum——

Complete o rastreamento

Preencha as etapas decisivas

Complete o rastreamento parcial do código da tela anterior. Preencha a condição, o elemento e os valores da atualização; depois, registre a ausência de acesso nas etapas bloqueadas.

cpp
// Etapa                  Índice  Condição       Acesso       Anterior  Posterior
// Atualização válida       1                         
// Validação rejeitada      3     falsa                 —        —
// Teste final do laço      3               nenhum       —        —

Confira o estado final e a coerência

Determine o vetor final

Depois de todas as etapas, escreva o conteúdo final de niveis na ordem dos índices 0, 1 e 2.

Localize uma divergência

Uma linha de rastreamento informa índice 2, mas registra o elemento acessado como niveis[1]. Qual conclusão é correta?

Confirme o encerramento seguro

Verdadeiro ou falso: no teste final, quando i = 3, o código lê niveis[3] antes de encerrar o for.

Passo 8 de 8

Aplicação final: confira um vetor seguro

Leia a solução e seus limites

Uma solução completa

Agora reúna as regras em um único sketch. A constante define tanto a quantidade de elementos quanto o limite exclusivo do percurso. Antes de alterar uma posição escolhida por uma variável, o código confirma que o índice está na faixa válida.

Faixa que protege o vetor

Diagrama de quatro células: a posição de índice 2 muda de 9 para 10; um percurso visita as posições de 0 a 3 e para no limite; tentativas de usar um índice negativo e o índice 4 são bloqueadas.

A quantidade é 4, mas o último índice válido é 3. Os limites bloqueiam índices negativos e o índice 4 antes da atualização.

Sketch para analisar

O vetor começa com quatro valores. O índice 2 é válido, portanto somente esse elemento aumenta em 1. Depois, o laço lê os índices 0, 1, 2 e 3 para calcular a soma, sem usar o índice 4.

cpp
#include <stdint.h>

const int QUANTIDADE = 4;
uint8_t valores[QUANTIDADE] = {3, 6, 9, 12};
int indiceParaAtualizar = 2;
uint16_t soma = 0;

void setup() {
  if (indiceParaAtualizar >= 0 && indiceParaAtualizar < QUANTIDADE) {
    valores[indiceParaAtualizar] += 1;
  }

  for (int i = 0; i < QUANTIDADE; i++) {
    soma += valores[i];
  }
}

void loop() {
}

Casos de fronteira

Confira cada situação pela faixa, não pelo fato de o sketch compilar.

Índices permitidos para QUANTIDADE igual a 4.
ÍndiceEstá na faixa?Atualização permitida?
-1NãoNão
0SimSim
2SimSim
3SimSim
4NãoNão

Reconstrua a proteção

Complete os limites

Complete os operadores que mantêm a atualização e o percurso dentro do vetor.

cpp
if (indiceParaAtualizar  0 && indiceParaAtualizar  QUANTIDADE) {
  valores[indiceParaAtualizar] += 1;
}

for (int i = 0; i  QUANTIDADE; i++) {
  soma += valores[i];
}

Cheque os extremos

Com QUANTIDADE = 4, qual alternativa reúne dois índices que a condição de atualização deve rejeitar?

Faça a conferência final

Preveja o vetor final

Sem executar o sketch, qual é o conteúdo final de valores depois de setup()?

Calcule a memória

No Uno R3, os elementos do vetor valores ocupam ___ bytes.

Justifique e conclua

Justifique os limites

Explique em uma ou duas frases por que a atualização usa indiceParaAtualizar >= 0 e indiceParaAtualizar < QUANTIDADE. Indique o que acontece com a atualização se a condição for falsa e o que ainda acontece depois no for.

Resumo

Síntese

  • Um vetor com quantidade N possui índices válidos de 0 a N − 1.
  • Quantidade não é o último índice: para 4 elementos, o último índice é 3.
  • Valide um índice variável antes de usá-lo; um índice negativo ou igual à quantidade não pode acessar o vetor.
  • No percurso simples, use i < QUANTIDADE para visitar cada elemento exatamente uma vez.
  • Memória dos elementos = quantidade × bytes de cada elemento; quatro uint8_t ocupam 4 bytes no Uno R3.
  • Compilar ou parecer funcionar não torna seguro um acesso fora da faixa.

Tutorial concluído

Parabéns! Você concluiu: Vetores de tamanho fixo e índices seguros

Você concluiu a análise de vetores fixos e índices seguros. Agora consegue declarar, atualizar, percorrer, conferir limites e estimar a memória dos elementos de um vetor.

20 XP

Baixe o Aplicativo agora para ter acesso a + de 5000 cursos gratuitos, exercícios, certificado e muito conteúdo sem pagar nada!

  • Cursos online 100% gratuitos do início ao fim

    Milhares de cursos online em vídeo, ebooks e áudiobooks.

  • Mais de 60 mil exercícios gratuitos

    Para testar seus conhecimentos no decorrer dos cursos online

  • Certificado Digital gratuito válido em todo o Brasil

    Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail

Aplicativo Cursa na tela de ebook, na tela de curso em vídeo e na tela de exercícios do curso, mais o certificado de conclusão de curso