C++ Variáveis

Todo programa precisa guardar coisas enquanto trabalha: a idade de uma pessoa, o preço de um caderno, quantas maçãs sobraram na lojinha da Ana. Em C++, cada coisa guardada fica numa variável. Nesta aula você vai criar suas primeiras variáveis, trocar o valor delas, conhecer as três formas de dar um valor inicial e entender por que o C++ reclama (ou, pior, não reclama) quando uma variável fica sem valor.

Você vai aprender
  • O que é uma variável e como criar uma: int idade = 29;.
  • Como trocar o valor e por que o tipo da variável nunca muda.
  • Como criar várias variáveis numa linha (e a armadilha que mora ali).
  • As três formas de inicializar: = 10, (10) e {10}, e o que as chaves impedem.
  • O que acontece com uma variável sem valor inicial (o "lixo") e os avisos -Wuninitialized e -Wmaybe-uninitialized.
  • Os erros de usar uma variável antes de criá-la e de criar duas com o mesmo nome.

Todos os programas desta aula foram compilados com o g++ 15.2 na máquina fictícia da Ana (usuária ana, computador notebook), na pasta ~/cpp, com o comando padrão do guia: g++ -std=c++23 -Wall -Wextra arquivo.cpp -o programa (cada opção é explicada em Compilar com g++). Você pode repetir cada um no editor do guia, que compila C++ de verdade no navegador.


A ideia: uma caixa com etiqueta e formato

Pense numa mudança de casa. Você guarda as coisas em caixas e escreve uma etiqueta em cada uma: "LIVROS", "PANELAS". Quando quer as panelas, procura pela etiqueta.

Uma variável é isso: um pedacinho da memória do computador com uma etiqueta. A etiqueta é o nome; o que está dentro é o valor. O nome "variável" vem daí: o que está dentro pode variar.

Em C++ existe um detalhe a mais: cada caixa tem um formato, escolhido quando você a cria, e esse formato nunca muda. Uma caixa de ovos só guarda ovos; uma caixa de sapatos só guarda sapatos. Esse formato se chama tipo.

Parte da caixaNome técnicoExemplo
O formato (o que cabe nela)tipoint (número inteiro), double (número com vírgula), std::string (texto)
A etiquetanomeidade, preco
O que está guardado agoravalor29, 4.5, "Ana"

Os tipos têm aula própria (Tipos de Dados). Por enquanto, três bastam: int (de integer, "inteiro") para números sem vírgula, double ("duplo", de precisão dupla) para números com vírgula e std::string ("sequência de caracteres") para textos.


1. Declarar uma variável

Criar uma variável se chama declarar. A receita é sempre a mesma: tipo nome = valor;.

#include <iostream>
#include <string>

int main() {
    int idade = 29;
    double altura = 1.65;
    std::string nome = "Ana";
    std::cout << nome << " tem " << idade << " anos e " << altura << " m de altura.\n";
}
#include <string>
Traz o tipo std::string para o programa. O int e o double já fazem parte da linguagem e não precisam de #include.
int
O tipo: esta caixa guarda um número inteiro.
idade
O nome da variável. As regras de nomes estão em Nomes de Variáveis.
=
Leia como "recebe": idade recebe 29. Não é o "igual" da matemática; quem compara valores é o == (aula Operadores de Comparação).
29
O valor inicial. Números não levam aspas.
;
O ponto e vírgula termina a declaração, como o ponto final de uma frase.
1.65
Número com vírgula se escreve com ponto, como nos Estados Unidos. 1,65 significaria outra coisa.
"Ana"
Texto vai entre aspas duplas (veja Strings).
std::cout << nome
Mostra o valor guardado em nome, e não a palavra "nome" (veja Saída com cout).
$ g++ -std=c++23 -Wall -Wextra ola.cpp -o ola
$ ./ola
Ana tem 29 anos e 1.65 m de altura.

O g++ não mostrou nada: isso quer dizer que compilou sem erros nem avisos. O ./ola rodou o programa, e cada << encaixou um pedaço da frase: o valor de nome, o texto " tem ", o valor de idade e assim por diante.

Experimente: troque os valores de fruta e quantidade e clique em Rodar. Depois crie uma terceira variável, double preco = 1.5;, e mostre-a também.

#include <iostream>
#include <string>

int main() {
    std::string fruta = "maçã";
    int quantidade = 6;
    std::cout << "A Ana comprou " << quantidade << " unidades de " << fruta << ".\n";
}

2. Mudar o valor

Depois de declarada, a variável é usada só pelo nome, sem repetir o tipo. Para trocar o valor, escreva nome = novo valor;. O valor antigo é jogado fora:

#include <iostream>

int main() {
    int macas = 6;
    std::cout << "Antes: " << macas << "\n";
    macas = 4;
    std::cout << "Depois: " << macas << "\n";
    macas = macas + 2;
    std::cout << "Mais duas: " << macas << "\n";
}
$ g++ -std=c++23 -Wall -Wextra mudar.cpp -o mudar
$ ./mudar
Antes: 6
Depois: 4
Mais duas: 6

O programa roda de cima para baixo. A linha macas = macas + 2; parece estranha para quem lembra da matemática, mas lembre que = é "recebe":

  1. O C++ calcula primeiro o lado direito: lê o valor atual de macas (4) e soma 2, dando 6.
  2. Depois guarda o resultado na caixa da esquerda, no lugar do 4.

Esse padrão tem um atalho, macas += 2;, explicado em Operadores de Atribuição.

Copiar uma variável para outra

int b = a; copia o valor. Depois disso, as duas caixas são independentes:

#include <iostream>

int main() {
    int a = 1;
    int b = a;
    a = 5;
    std::cout << "a=" << a << " b=" << b << "\n";
}
$ ./copia
a=5 b=1                  « mudar a depois não mexeu em b

O tipo nunca muda

Uma caixa de int continua sendo de int até o fim. Tentar guardar um texto nela é recusado pelo compilador:

#include <iostream>

int main() {
    int idade = 29;
    idade = "trinta";
    std::cout << idade << "\n";
}
$ g++ -std=c++23 -Wall -Wextra tipo.cpp -o tipo
tipo.cpp: In function ‘int main()’:
tipo.cpp:5:13: error: invalid conversion from ‘const char*’ to ‘int’ [-fpermissive]
    5 |     idade = "trinta";
      |             ^~~~~~~~
      |             |
      |             const char*

Invalid conversion from ‘const char*’ to ‘int’ = "conversão inválida de const char* para int". O const char* é o tipo que o C++ dá a um texto entre aspas (a aula Strings conta essa história); o compilador está dizendo "isso é texto, e a caixa é de inteiro". Como é um error, o arquivo tipo nem foi criado. (A leitura da mensagem, parte por parte, está em Lendo Erros do Compilador.)

Já um número com vírgula numa caixa de int passa sem nenhum aviso, e a parte depois da vírgula some:

#include <iostream>

int main() {
    int idade = 29;
    idade = 29.9;
    std::cout << idade << "\n";
}
$ g++ -std=c++23 -Wall -Wextra corta.cpp -o corta
$ ./corta
29                       « o .9 foi cortado (não arredondado), em silêncio

O C++ converte o 29.9 para int jogando fora a parte fracionária. Isso tem aula própria, Conversão de Tipos. A próxima seção mostra um jeito de fazer o compilador barrar esse corte já na criação da variável.


3. Várias variáveis numa linha

Variáveis do mesmo tipo podem ser declaradas juntas, separadas por vírgula:

#include <iostream>

int main() {
    int a = 1, b = 2, c = 3;
    std::cout << a << " " << b << " " << c << "\n";
    int x, y = 5;
    std::cout << x << " " << y << "\n";
}
$ g++ -std=c++23 -Wall -Wextra linha.cpp -o linha
linha.cpp: In function ‘int main()’:
linha.cpp:7:18: warning: ‘x’ is used uninitialized [-Wuninitialized]
    7 |     std::cout << x << " " << y << "\n";
      |                  ^
linha.cpp:6:9: note: ‘x’ was declared here
    6 |     int x, y = 5;
      |         ^
$ ./linha
1 2 3
0 5

A linha 4 está certa: três variáveis, cada uma com seu valor. A linha 6 é a armadilha: quem lê int x, y = 5; pode achar que as duas valem 5, mas o = 5 vale só para o y. O x ficou sem valor, e o compilador avisou. Aqui ele apareceu como 0 por acaso; a seção 5 mostra que ele poderia ser qualquer número.

Uma variável por linha

Declarar várias numa linha economiza espaço, mas esconde erros como esse. A maioria dos guias de estilo recomenda uma declaração por linha, cada uma com seu valor. Variáveis de tipos diferentes (um int e um double) nunca podem ir na mesma linha.


4. Três formas de dar o valor inicial

O C++ aceita três escritas para inicializar uma variável. As três abaixo criam um int:

#include <iostream>

int main() {
    int a = 10;
    int b(20);
    int c{30};
    int d{};
    std::cout << a << " " << b << " " << c << " " << d << "\n";
}
$ g++ -std=c++23 -Wall -Wextra formas.cpp -o formas
$ ./formas
10 20 30 0
int a = 10;
Com sinal de igual: a forma que veio da linguagem C, a mais comum de ler.
int b(20);
Com parênteses: herança do C++ antigo. Você vai vê-la de novo em Construtores.
int c{30};
Com chaves C++11: a "inicialização uniforme", que funciona do mesmo jeito para números, textos, listas e objetos.
int d{};
Chaves vazias: o valor "zero" do tipo. Para int, 0; para double, 0.0; para std::string, o texto vazio. É o jeito mais curto de nunca deixar uma variável sem valor.

O que as chaves impedem: o estreitamento (narrowing)

Você viu na seção 2 que int idade = 29.9; passa em silêncio e vira 29. Com chaves, o compilador recusa:

#include <iostream>

int main() {
    int x{3.7};
    std::cout << x << "\n";
}
$ g++ -std=c++23 -Wall -Wextra estreita.cpp -o estreita
estreita.cpp: In function ‘int main()’:
estreita.cpp:4:11: error: narrowing conversion of ‘3.7000000000000002e+0’ from ‘double’ to ‘int’ [-Wnarrowing]
    4 |     int x{3.7};
      |           ^~~
narrowing conversion
"Conversão de estreitamento": passar um valor para um tipo mais "estreito", onde ele não cabe inteiro. O 3.7 não cabe num int sem perder o .7.
of ‘3.7000000000000002e+0’
É o seu 3.7, escrito do jeito que o computador o guarda de verdade: em notação científica (e+0 = "vezes 10 elevado a 0") e com um errinho na 16ª casa. Esse errinho é normal e é explicado em float e double.
from ‘double’ to ‘int’
De qual tipo para qual tipo.
[-Wnarrowing]
O nome da regra. Apesar do -W (de warning), aqui é um error: o programa não foi gerado.

Compare com a mesma conta usando =:

$ cat estreita2.cpp
#include <iostream>

int main() {
    int x = 3.7;
    std::cout << x << "\n";
}
$ g++ -std=c++23 -Wall -Wextra estreita2.cpp -o estreita2
$ ./estreita2
3                        « nenhum aviso, e o .7 sumiu

Nem o -Wall -Wextra avisou. Existe uma opção que avisa, o -Wconversion (ela não faz parte do -Wall; a aula Avisos fala dela):

$ g++ -std=c++23 -Wall -Wextra -Wconversion estreita2.cpp -o estreita2
estreita2.cpp: In function ‘int main()’:
estreita2.cpp:4:13: warning: conversion from ‘double’ to ‘int’ changes value from ‘3.7000000000000002e+0’ to ‘3’ [-Wfloat-conversion]
    4 |     int x = 3.7;
      |             ^~~

O Clang, o compilador do editor do guia, é um pouco mais atento: quando o número está escrito direto no código, ele avisa mesmo sem -Wall (implicit conversion from 'double' to 'int' changes value from 3.7 to 3 [-Wliteral-conversion]). Mas é só um aviso, e o programa é gerado. Com chaves, você ganha um erro nos dois compiladores, sem opção extra.

Missão: este programa compila e mostra Preço: 9, perdendo os centavos (o Clang do editor até mostra um aviso, mas gera o programa mesmo assim). Troque int preco = 9.99; pela forma com chaves e rode: o compilador tem que recusar o estreitamento. (O editor usa o Clang, que escreve cannot be narrowed; o g++ escreve narrowing conversion. Os dois dizem a mesma coisa.)

#include <iostream>

int main() {
    int preco = 9.99;
    std::cout << "Preço: " << preco << "\n";
}
#include <iostream>

int main() {
    int preco{9.99};
    std::cout << "Preço: " << preco << "\n";
}

E o conserto de verdade? Preço tem centavos, então a caixa certa é double preco{9.99};. O erro de narrowing quase sempre quer dizer "você escolheu o tipo errado".

Qual usar

FormaBarra o estreitamento?Quando usar
int x = 10;NãoValores simples e óbvios. É a mais lida em código do dia a dia, e o guia usa bastante.
int x(10);NãoRaramente para números; aparece com objetos e construtores.
int x{10};SimQuando o valor vem de uma conta ou de outra variável e você quer que o compilador vigie perdas.
int x{};(vale zero)Quando você ainda não sabe o valor, mas quer começar do zero com segurança.

5. Variável sem valor inicial: o "lixo"

O C++ deixa você criar uma variável sem valor: int pontos;. Ela existe, ocupa memória, mas o C++ não limpa essa memória. O que estiver lá, sobrado de outra parte do programa, vira o "valor". Programadores chamam isso de lixo (garbage).

Neste programa, a função prepara usa um pedaço da memória e termina; depois a função mostra cria pontos sem valor. (Funções são do Nível 2, em Funções; aqui elas só servem para "sujar" a memória antes.)

#include <iostream>

void prepara() {
    int numeros[4] = {1234, 5678, 9012, 3456};
    std::cout << "prepara usou: " << numeros[0] << "\n";
}

void mostra() {
    int pontos;
    std::cout << "pontos vale: " << pontos << "\n";
}

int main() {
    prepara();
    mostra();
}
$ g++ -std=c++23 -Wall -Wextra lixo.cpp -o lixo
lixo.cpp: In function ‘void mostra()’:
lixo.cpp:10:37: warning: ‘pontos’ is used uninitialized [-Wuninitialized]
   10 |     std::cout << "pontos vale: " << pontos << "\n";
      |                                     ^~~~~~
lixo.cpp:9:9: note: ‘pontos’ was declared here
    9 |     int pontos;
      |         ^~~~~~
$ ./lixo
prepara usou: 1234
pontos vale: 67871226
$ ./lixo
prepara usou: 1234
pontos vale: 643496078
$ ./lixo
prepara usou: 1234
pontos vale: -2034654050  « três execuções, três valores diferentes
warning:
"Aviso". Diferente de error, o programa foi gerado. Mas este aviso é sério.
‘pontos’ is used uninitialized
"pontos é usada sem ter sido inicializada": você leu o valor de uma caixa onde nunca guardou nada.
[-Wuninitialized]
A regra de aviso que pegou o problema. Ela vem ligada pelo -Wall.
note: ‘pontos’ was declared here
"Nota: pontos foi declarada aqui": o compilador aponta a linha da criação, onde está o conserto.

O número muda a cada execução e não tem nenhum significado. Num jogo, a Ana começaria a partida com 643 milhões de pontos. Ler uma variável sem valor é um comportamento indefinido: a linguagem não promete nada sobre o que acontece (aula Comportamento Indefinido). Às vezes o lixo é 0, como na seção 3, e o erro passa despercebido nos testes para aparecer depois.

Regra do guia: toda variável nasce com valor

Sempre que puder, dê o valor já na declaração: int pontos = 0; ou int pontos{};. Se ainda não souber o valor certo, comece com zero. E nunca ignore um aviso uninitialized.

"Talvez sem valor": -Wmaybe-uninitialized

Às vezes a variável recebe valor só em alguns caminhos do programa. Aqui, desconto só recebe valor se a Ana fez mais de 5 compras (o if tem aula própria, if e else; o std::cin lê um número do teclado, aula Entrada com cin):

#include <iostream>

int main() {
    int compras = 0;
    std::cin >> compras;
    int desconto;
    if (compras > 10) {
        desconto = 5;
    } else if (compras > 5) {
        desconto = 2;
    }
    std::cout << "Desconto: " << desconto << "%\n";
}
$ g++ -std=c++23 -Wall -Wextra talvez.cpp -o talvez     « nenhum aviso!
$ g++ -std=c++23 -Wall -Wextra -O2 talvez.cpp -o talvez
talvez.cpp: In function ‘int main()’:
talvez.cpp:12:34: warning: ‘desconto’ may be used uninitialized [-Wmaybe-uninitialized]
   12 |     std::cout << "Desconto: " << desconto << "%\n";
      |                                  ^~~~~~~~
talvez.cpp:6:9: note: ‘desconto’ was declared here
    6 |     int desconto;
      |         ^~~~~~~~
$ echo 3 | ./talvez
Desconto: 5%             « 3 compras não dão desconto, mas saiu 5%
  • May be used uninitialized = "pode ser usada sem valor". O compilador não tem certeza (depende do número digitado), mas achou um caminho em que nenhum valor é guardado: 5 compras ou menos.
  • No g++, esse aviso só aparece quando você também pede otimização (-O2, "otimize, nível 2"), porque a análise que encontra esses caminhos roda junto com a otimização. Sem -O2, o mesmo erro passou calado.
  • O resultado 5% com 3 compras é o comportamento indefinido em ação: o otimizador supôs que o caminho sem valor nunca acontece.
  • O conserto é o mesmo: int desconto = 0;.
No editor do guia

O editor compila com o Clang, que pega este caso mesmo sem otimização, com outras palavras: variable 'desconto' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized] ("é usada sem valor sempre que a condição do if for falsa"). Para o lixo.cpp, o Clang escreve variable 'pontos' is uninitialized when used here [-Wuninitialized]. Duas ferramentas, a mesma lição.

Missão: rode e leia o aviso: qual variável está sem valor? Conserte só a linha da declaração dela, para o programa mostrar Pontos: 10 sem nenhum aviso.

#include <iostream>

int main() {
    int pontos;
    int bonus = 10;
    pontos = pontos + bonus;
    std::cout << "Pontos: " << pontos << "\n";
}
#include <iostream>

int main() {
    int pontos = 0;
    int bonus = 10;
    pontos = pontos + bonus;
    std::cout << "Pontos: " << pontos << "\n";
}

No laboratório, esse programa com defeito mostrou Pontos: 10 (o lixo daquela vez era zero), mas com o aviso ‘pontos’ is used uninitialized. "Deu o número certo" não quer dizer que está certo.


6. Usar antes de declarar e declarar duas vezes

O compilador lê o arquivo de cima para baixo. Uma variável só existe da linha da declaração para baixo:

#include <iostream>

int main() {
    std::cout << total << "\n";
    int total = 50;
}
$ g++ -std=c++23 -Wall -Wextra antes.cpp -o antes
antes.cpp: In function ‘int main()’:
antes.cpp:4:18: error: ‘total’ was not declared in this scope
    4 |     std::cout << total << "\n";
      |                  ^~~~~

‘total’ was not declared in this scope = "total não foi declarada neste escopo". Escopo é a região do código onde um nome existe (aula Escopo); na linha 4, total ainda não existe. O mesmo erro aparece quando o nome está escrito diferente (Total, totla). O Clang, no editor, diz use of undeclared identifier 'total' ("uso de identificador não declarado").

E criar duas variáveis com o mesmo nome no mesmo lugar também é erro:

#include <iostream>

int main() {
    int total = 50;
    int total = 80;
    std::cout << total << "\n";
}
$ g++ -std=c++23 -Wall -Wextra dupla.cpp -o dupla
dupla.cpp: In function ‘int main()’:
dupla.cpp:5:9: error: redeclaration of ‘int total’
    5 |     int total = 80;
      |         ^~~~~
dupla.cpp:4:9: note: ‘int total’ previously declared here
    4 |     int total = 50;
      |         ^~~~~

Redeclaration = "declaração repetida"; previously declared here = "declarada antes aqui". Para mudar o valor, escreva sem o tipo: total = 80;. Repetir o int pede uma caixa nova com uma etiqueta que já existe.


Quando dá errado

error: ‘x’ was not declared in this scope

O que significa: na linha indicada, o nome não existe. Causas: a declaração está mais abaixo, o nome está escrito diferente (maiúscula, acento, letra trocada) ou a variável foi criada dentro de outro bloco { }.

Como consertar: copie o nome da mensagem e procure-o no arquivo. Confira se a declaração vem antes da linha do erro e se o nome é idêntico.

warning: ‘x’ is used uninitialized / may be used uninitialized

O que significa: o programa lê uma variável que não recebeu valor (ou pode não ter recebido, em algum caminho). O valor lido é lixo.

Como consertar: dê um valor na declaração apontada pela note: ‘x’ was declared here: int x = 0; ou int x{};.

error: narrowing conversion of … from ‘double’ to ‘int’

O que significa: dentro de chaves, você pôs um valor que não cabe inteiro no tipo da variável.

Como consertar: quase sempre o tipo está errado: use double para valores com vírgula. Se você quer mesmo cortar, diga isso por escrito com static_cast<int>(3.7) (aula Conversão de Tipos).

error: redeclaration of ‘int x’

O que significa: o mesmo nome foi declarado duas vezes no mesmo bloco.

Como consertar: para trocar o valor, tire o tipo da segunda linha (x = 80;). Se são duas coisas diferentes, dê nomes diferentes.

error: invalid conversion from ‘const char*’ to ‘int’

O que significa: você tentou guardar um texto entre aspas numa variável de número.

Como consertar: se é texto, a variável deve ser std::string; se é número, tire as aspas (30, e não "30"). Para transformar texto em número de propósito, veja Texto ↔ Número.

error: expected initializer before ‘return’

O que significa: faltou o ; no fim da declaração (por exemplo, int x seguido de return 0; na linha de baixo). O compilador continuou lendo e tropeçou na próxima palavra.

Como consertar: quando o erro aponta uma linha que parece certa, olhe o fim da linha anterior.


Referência rápida

EscritaO que faz
int x = 10;Declara x com valor 10
int x(10);O mesmo, com parênteses
int x{10};O mesmo, com chaves: recusa estreitamento
int x{};Declara x valendo zero
int x;Declara sem valor: lixo até receber um (evite)
x = 20;Troca o valor (sem repetir o tipo)
x = x + 1;Calcula com o valor atual e guarda o resultado
int b = a;Copia o valor de a; as duas ficam independentes
int a = 1, b = 2;Várias do mesmo tipo numa linha (cada uma com seu valor)

Exercícios

1. Declarar

Complete para criar uma variável inteira alunos valendo 32:

alunos = 32;

2. Começar do zero

Complete com a forma de chaves que dá o valor zero:

int pontos;

3. Depois de int x, y = 5;, quanto vale x?

4. O que acontece com int n{2.5};?

5. O que o programa mostra? int a = 2; int b = a; a = 7; std::cout << b;

6. A linha 5 tem int total = 80; e a linha 4 já tinha int total = 50;. O que o g++ diz?

Missão final: o caixa da lojinha

Missão: a Ana vendeu 3 cadernos a 2.5 cada. Declare quantidade (int, valendo 3, com chaves) e preco (double, valendo 2.5), calcule total (double) como quantidade * preco (o * é "vezes") e mostre a primeira linha. Depois a cliente pegou mais um caderno: mude quantidade para 4, calcule o total de novo e mostre a segunda linha. Sem avisos.

Total: 7.5
Total: 10
#include <iostream>

int main() {
    // declare quantidade, preco e total aqui

    // mostre o total

    // mude a quantidade, recalcule e mostre de novo
}
#include <iostream>

int main() {
    int quantidade{3};
    double preco{2.5};
    double total{quantidade * preco};
    std::cout << "Total: " << total << "\n";

    quantidade = 4;
    total = quantidade * preco;
    std::cout << "Total: " << total << "\n";
}

Repare que o segundo total saiu 10, e não 10.0: o std::cout esconde os zeros desnecessários de um double. Para mostrar 10.00, veja Formatar com iomanip.


Resumo

  • Variável = caixa com tipo (formato), nome (etiqueta) e valor. Declare com tipo nome = valor;.
  • Para mudar o valor: nome = novo;, sem repetir o tipo. O lado direito é calculado primeiro. O tipo nunca muda.
  • Várias numa linha: int a = 1, b = 2;. Em int x, y = 5;, só o y vale 5. Prefira uma por linha.
  • Três formas: = 10, (10), {10}. As chaves recusam o estreitamento (int x{3.7}; é erro); {} vazio dá zero.
  • Variável sem valor guarda lixo. -Wall avisa com -Wuninitialized; o -Wmaybe-uninitialized do g++ aparece com -O2. Regra: toda variável nasce com valor.
  • A variável só existe da declaração para baixo (was not declared in this scope), e o mesmo nome não pode ser declarado duas vezes no mesmo bloco (redeclaration).