C++ Nomes de Variáveis

Na aula Variáveis, você criou caixas com etiquetas como idade e preco. Essas etiquetas têm um nome técnico: identificadores (de "identificar"). O mesmo tipo de nome serve para funções, classes e tudo o que você batiza no programa. Nesta aula você vai ver o que o C++ exige de um nome, quais palavras ele guarda para si, por que nota e Nota são coisas diferentes e como escolher nomes que deixam o programa fácil de ler.

Você vai aprender
  • As regras de um nome válido e os erros reais de quem as quebra.
  • As palavras reservadas (int, return, class…), que não podem ser nomes.
  • Por que maiúsculas e minúsculas fazem diferença.
  • As convenções camelCase e snake_case.
  • Como reconhecer um nome bom e um nome ruim.
  • Se o g++ 15 aceita int ação (aceita) e por que mesmo assim é melhor evitar.

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.


A ideia: regras × combinados

Pense no nome de uma criança no cartório. Existem regras que o cartório confere (não pode ter número, não pode ser vazio) e existem costumes que ninguém confere, mas todo mundo segue (nome com inicial maiúscula, sobrenome no fim).

No C++ é igual:

  • Regras: o compilador confere. Quebrou, o programa não compila.
  • Convenções: combinados entre programadores para o código ficar legível. O compilador não liga, mas as pessoas que vão ler o seu código (inclusive você daqui a um mês) ligam muito.

1. As regras

  1. Um nome usa letras, algarismos (0 a 9) e o sublinhado _.
  2. O primeiro caractere é uma letra ou _. Nunca um algarismo.
  3. Sem espaços, sem hífen, sem pontuação (-, ., !, @…).
  4. Não pode ser uma palavra reservada da linguagem (seção 2).
  5. Não existe limite prático de tamanho: quantidadeDeMacasNaPrateleira é válido.

Todos estes são válidos:

#include <iostream>

int main() {
    int idade = 29;
    int item2 = 7;
    int _total = 100;
    int nomeCompleto = 1;
    int nome_completo = 2;
    int NOTA_MAXIMA = 10;
    std::cout << idade << " " << item2 << " " << _total << " "
              << nomeCompleto << " " << nome_completo << " " << NOTA_MAXIMA << "\n";
}
$ g++ -std=c++23 -Wall -Wextra validos.cpp -o validos
$ ./validos
29 7 100 1 2 10

Repare que nomeCompleto e nome_completo convivem no mesmo programa: para o C++, são nomes diferentes. (Fazer isso de propósito é péssima ideia; aqui é só para provar a regra.)

Começar com algarismo

#include <iostream>

int main() {
    int 2lugar = 1;
    std::cout << 2lugar << "\n";
}
$ g++ -std=c++23 -Wall -Wextra a.cpp -o a
a.cpp: In function ‘int main()’:
a.cpp:4:9: error: expected unqualified-id before numeric constant
    4 |     int 2lugar = 1;
      |         ^~~~~~
a.cpp:5:18: error: unable to find numeric literal operator ‘operator""lugar’
    5 |     std::cout << 2lugar << "\n";
      |                  ^~~~~~
a.cpp:5:18: note: use ‘-fext-numeric-literals’ to enable more built-in suffixes
expected unqualified-id before numeric constant
"Esperava um identificador antes da constante numérica". Ao ver o 2, o compilador entendeu "aqui começa um número", e não um nome.
unable to find numeric literal operator ‘operator""lugar’
Na linha 5, ele leu 2lugar como o número 2 seguido de um "sufixo" chamado lugar (sufixos existem, como o s de "oi"s, visto em auto) e não achou esse sufixo.
note: use ‘-fext-numeric-literals’…
Uma dica que não se aplica ao seu caso. Notas do compilador às vezes chutam errado: o conserto real é mudar o nome.

Conserto: segundoLugar ou lugar2.

Hífen e espaço

$ cat b.cpp
#include <iostream>

int main() {
    int minha-variavel = 1;
    std::cout << minha-variavel << "\n";
}
$ g++ -std=c++23 -Wall -Wextra b.cpp -o b
b.cpp: In function ‘int main()’:
b.cpp:4:14: error: expected initializer before ‘-’ token
    4 |     int minha-variavel = 1;
      |              ^
b.cpp:5:18: error: ‘minha’ was not declared in this scope
    5 |     std::cout << minha-variavel << "\n";
      |                  ^~~~~
b.cpp:5:24: error: ‘variavel’ was not declared in this scope
    5 |     std::cout << minha-variavel << "\n";
      |                        ^~~~~~~~

O hífen é o sinal de menos. O compilador leu minha - variavel: uma conta entre duas variáveis, minha e variavel, que não existem. Por isso os dois erros was not declared na linha 5. Na linha 4, ele esperava um valor inicial (initializer) e achou o -.

$ g++ -std=c++23 -Wall -Wextra c.cpp -o c       « int minha variavel = 1;
c.cpp: In function ‘int main()’:
c.cpp:4:15: error: expected initializer before ‘variavel’
    4 |     int minha variavel = 1;
      |               ^~~~~~~~
c.cpp:5:18: error: ‘minha’ was not declared in this scope
    5 |     std::cout << minha variavel << "\n";
      |                  ^~~~~

O espaço termina o nome. O compilador viu uma variável chamada minha e depois uma palavra solta, variavel, onde esperava = ou ;.

Conserto: junte as palavras com sublinhado ou com maiúscula: minha_variavel ou minhaVariavel.

Missão: o boletim da Ana não compila: os dois nomes quebram as regras. Rode, leia os erros e troque os nomes (nas duas linhas em que cada um aparece) por nomes válidos, como primeiroColocado e notaFinal.

#include <iostream>

int main() {
    int 1colocado = 95;
    int nota-final = 87;
    std::cout << "Primeiro: " << 1colocado << "\n";
    std::cout << "Nota final: " << nota-final << "\n";
}
#include <iostream>

int main() {
    int primeiroColocado = 95;
    int notaFinal = 87;
    std::cout << "Primeiro: " << primeiroColocado << "\n";
    std::cout << "Nota final: " << notaFinal << "\n";
}

Nomes com sublinhado no começo: permitidos, mas reservados

Dois padrões de nome são válidos para o compilador, mas a norma do C++ os reserva para o próprio compilador e para a biblioteca padrão:

  • começar com _ seguido de letra maiúscula: _Total;
  • ter dois sublinhados seguidos em qualquer lugar: __x, meu__nome.

O g++ compila esses nomes sem reclamar, mas um dia eles podem colidir com algo interno da biblioteca. O Clang tem um aviso específico, que não vem no -Wall:

$ clang++ -std=c++23 -Wall -Wextra -Wreserved-identifier res.cpp -o res
res.cpp:2:9: warning: identifier '_Total' is reserved because it starts with '_' followed by a capital letter [-Wreserved-identifier]
    2 |     int _Total = 1;
      |         ^
res.cpp:3:9: warning: identifier '__x' is reserved because it starts with '__' [-Wreserved-identifier]
    3 |     int __x = 2;
      |         ^
2 warnings generated.

Regra prática: não comece nomes com sublinhado. Assim você nunca precisa lembrar quais casos são reservados.


2. Palavras reservadas

Algumas palavras já têm significado para o C++: int, if, return… Elas se chamam palavras-chave (keywords) ou palavras reservadas, e nenhuma delas pode ser nome de variável:

$ cat h.cpp
int main() {
    int return = 1;
}
$ g++ -std=c++23 -Wall -Wextra h.cpp -o h
h.cpp: In function ‘int main()’:
h.cpp:2:9: error: expected unqualified-id before ‘return’
    2 |     int return = 1;
      |         ^~~~~~
$ g++ -std=c++23 -Wall -Wextra e.cpp -o e       « int new = 1;
e.cpp: In function ‘int main()’:
e.cpp:2:9: error: expected unqualified-id before ‘new’
    2 |     int new = 1;
      |         ^~~
$ g++ -std=c++23 -Wall -Wextra d.cpp -o d       « int class = 1;
d.cpp: In function ‘int main()’:
d.cpp:2:5: error: expected primary-expression before ‘int’
    2 |     int class = 1;
      |     ^~~

Expected unqualified-id = "esperava um identificador (um nome)". O compilador achou uma palavra-chave onde deveria vir um nome. O erro do class é mais confuso (aponta para o int), porque int class parece o começo de outra construção. Quando uma mensagem não faz sentido numa linha simples, desconfie de uma palavra reservada.

O C++23 tem 92 palavras-chave. No laboratório, cada uma delas foi testada como nome de variável (int PALAVRA = 1;), e o g++ 15 recusou as 92. Você não precisa decorá-las: a maioria você vai aprender aula a aula, e os editores costumam pintá-las de outra cor.

AssuntoPalavras-chaveOnde aparecem
Tiposbool char char8_t char16_t char32_t wchar_t short int long signed unsigned float double void autoTipos de Dados, auto
Valorestrue false nullptr thisbool, nullptr, this
Decisõesif else switch case defaultif e else, switch
Repetições e saltosfor while do break continue return gotofor, while, break e continue
Constantes e armazenamentoconst constexpr consteval constinit static extern mutable volatile register thread_local inlineConstantes, constexpr e consteval
Tipos próprios e classesstruct class union enum public private protected friend virtual explicit operator typedef using namespaceStructs, Classes
Memórianew delete sizeof alignof alignasnew e delete
Conversões e tiposstatic_cast dynamic_cast const_cast reinterpret_cast typeid decltypeConversão de Tipos
Errostry catch throw noexcept static_assertExceções
Templatestemplate typename concept requiresTemplates, Concepts
Corrotinas, módulos, outrosco_await co_return co_yield export asm(avançado; Módulos)
Operadores escritos por extensoand or not xor and_eq or_eq xor_eq not_eq bitand bitor complOperadores Lógicos
cout, string e main não são palavras-chave

cout e string são nomes que a biblioteca padrão criou dentro do std. main é só o nome que o sistema procura para começar. Por isso o programa abaixo compila, e as variáveis cout e string convivem com std::cout e std::string:

$ cat cout.cpp
#include <iostream>
#include <string>

int main() {
    int cout = 5;
    std::string string = "texto";
    std::cout << cout << " " << string << "\n";
}
$ g++ -std=c++23 -Wall -Wextra cout.cpp -o cout
$ ./cout
5 texto

Funciona, mas confunde qualquer leitor. O mesmo vale para final e override, que só são especiais em certos lugares (aula Polimorfismo): int final = 1; compila. Evite todos eles como nomes.


3. Maiúsculas e minúsculas fazem diferença

Para o C++, nota, Nota e NOTA são três nomes diferentes. Isso se diz assim: o C++ é case-sensitive ("sensível à caixa", isto é, a letras maiúsculas e minúsculas). Uma letra trocada já basta para o compilador não achar a variável:

#include <iostream>

int main() {
    int nota = 8;
    std::cout << Nota << "\n";
}
$ g++ -std=c++23 -Wall -Wextra g.cpp -o g
g.cpp: In function ‘int main()’:
g.cpp:5:18: error: ‘Nota’ was not declared in this scope; did you mean ‘nota’?
    5 |     std::cout << Nota << "\n";
      |                  ^~~~
      |                  nota
g.cpp:4:9: warning: unused variable ‘nota’ [-Wunused-variable]
    4 |     int nota = 8;
      |         ^~~~
‘Nota’ was not declared in this scope
"Nota não foi declarada": com N maiúsculo, ela não existe.
did you mean ‘nota’?
"Você quis dizer nota?" O g++ procura um nome parecido e sugere. A linha de baixo, com nota embaixo do ^~~~, mostra como ficaria a correção.
warning: unused variable ‘nota’
Consequência do mesmo engano: como o programa nunca usou nota (com n minúsculo), o compilador avisa que ela foi criada à toa.

As palavras-chave também são sensíveis: Int ou RETURN não são palavras do C++. Tudo o que é da linguagem e da biblioteca padrão é escrito em minúsculas.


4. Convenções: como escrever nomes de várias palavras

Como não pode haver espaço, os programadores juntam as palavras de um destes jeitos:

EstiloExemploComo éQuem usa
camelCase ("caixa de camelo")precoTotalPrimeira palavra minúscula; as outras começam com maiúscula, como as corcovas de um camelo.Muitos projetos C++ (e Java, JavaScript). É o estilo deste guia para variáveis.
snake_case ("caixa de cobra")preco_totalTudo minúsculo, palavras ligadas por _, como uma cobra rastejando.A biblioteca padrão do C++ (std::to_string, push_back, numeric_limits) e muitos projetos.
PascalCaseContaBancariaTodas as palavras com maiúscula.Costuma ser reservado para tipos que você cria (structs e classes).
MAIÚSCULAS_COM_SUBLINHADONOTA_MAXIMATudo maiúsculo.Tradicionalmente, macros do #define (aula Constantes). Alguns projetos usam também para constantes.

Nenhum é "o certo". O importante é escolher um por projeto e seguir sempre. Se você entra num projeto que já existe, use o estilo que ele já usa.


5. Nomes bons e nomes ruins

Um nome bom responde à pergunta "o que tem nesta caixa?" sem que o leitor precise caçar o resto do código. Compare duas versões do mesmo programa:

int a = 3;
double b = 2.5;
double c = a * b;
int quantidade = 3;
double precoUnitario = 2.5;
double total = quantidade * precoUnitario;

As duas fazem exatamente a mesma conta e geram o mesmo programa. Mas só a segunda dá para entender sem explicação.

RuimPor quêMelhor
x, a, n2Não diz nada.idade, alunos
qtdPrdEstAbreviação que só o autor entende.quantidadeEmEstoque
dados, valor, coisaGenérico demais: todo valor é um "dado".notaDaProva, saldo
numeroDeAlunosMatriculadosNaTurmaDoTerceiroAnoLongo demais para ler e digitar.alunosTerceiroAno
l, O, IConfundem-se com 1 e 0 em muitas fontes.linha, total
temp2, testeSobras de testes que ficam para sempre.Um nome que diga o papel da variável.
Exceções aceitas

Nomes de uma letra são normais em lugares curtos e tradicionais: i, j como contador de um for, x e y para coordenadas. Fora disso, escreva por extenso.


6. Acentos nos nomes: o g++ 15 aceita int ação?

Aceita. Desde o C++11, a norma permite letras de outros alfabetos em nomes, e o C++23 definiu exatamente quais (as letras do padrão Unicode, um catálogo de todos os caracteres do mundo; a aula Acentos e UTF-8 explica). O g++ 15 e o Clang 21 aceitam:

#include <iostream>

int main() {
    int ação = 3;
    double preço = 4.5;
    double π = 3.14159;
    std::cout << ação << " " << preço << " " << π << "\n";
}
$ g++ -std=c++23 -Wall -Wextra acento.cpp -o acento
$ ./acento
3 4.5 3.14159
$ g++ -std=c++23 -Wall -Wextra -pedantic acento.cpp -o acento    « nem o modo rigoroso reclama
$ clang++ -std=c++23 -Wall -Wextra acento.cpp -o acento-clang
$ ./acento-clang
3 4.5 3.14159

E um emoji? A norma diz que não (emoji não é letra). O Clang segue a norma; o g++ só recusa no modo rigoroso:

$ cat emoji.cpp
#include <iostream>

int main() {
    int 😀 = 1;
    std::cout << 😀 << "\n";
}
$ g++ -std=c++23 -Wall -Wextra emoji.cpp -o emoji
$ ./emoji
1                        « o g++ deixou passar, como extensão própria
$ g++ -std=c++23 -Wall -Wextra -pedantic emoji.cpp -o emoji
emoji.cpp:4:9: error: extended character 😀 is not valid in an identifier
    4 |     int 😀 = 1;
      |         ^
emoji.cpp:5:18: error: extended character 😀 is not valid in an identifier
    5 |     std::cout << 😀 << "\n";
      |                  ^
$ clang++ -std=c++23 -Wall -Wextra emoji.cpp -o emoji
emoji.cpp:4:9: error: unexpected character <U+1F600>
    4 |     int 😀 = 1;
      |         ^~
emoji.cpp:4:14: error: expected unqualified-id
    4 |     int 😀 = 1;
      |            ^
emoji.cpp:5:18: error: unexpected character <U+1F600>
    5 |     std::cout << 😀 << "\n";
      |                  ^~
emoji.cpp:5:23: error: expected expression
    5 |     std::cout << 😀 << "\n";
      |                     ^
4 errors generated.

Por que, mesmo assim, evitar acentos

Uma letra acentuada pode ser guardada no arquivo de dois jeitos: o ç "pronto" (um caractere só) ou um c seguido de um "cedilha solto" que se encaixa nele. Na tela, os dois são idênticos. Para o compilador, são nomes diferentes. Veja o que acontece quando a declaração foi digitada de um jeito e o uso, de outro (isso acontece ao copiar e colar de páginas web, PDFs ou do macOS):

#include <iostream>

int main() {
    double preço = 4.5;
    std::cout << preço << "\n";
}
$ g++ -std=c++23 -Wall -Wextra normal.cpp -o normal
normal.cpp:4:12: warning: ‘prec\U00000327o’ is not in NFC [-Wnormalized=]
    4 |     double prec<U+0327>o = 4.5;
      |            ^~~~~~~~~~~~~
normal.cpp: In function ‘int main()’:
normal.cpp:5:18: error: ‘preço’ was not declared in this scope; did you mean ‘preço’?
    5 |     std::cout << preço << "\n";
      |                  ^~~~~
      |                  preço
normal.cpp:4:12: warning: unused variable ‘preço’ [-Wunused-variable]
    4 |     double preço = 4.5;
      |            ^~~~~
  • is not in NFC: o g++ avisa que o nome não está na forma "pronta" (NFC, a forma normal composta, a que a norma exige). Repare como ele mostra o cedilha solto: prec<U+0327>o.
  • ‘preço’ was not declared in this scope; did you mean ‘preço’?: "preço não foi declarada; você quis dizer preço?". Os dois nomes parecem iguais, e mesmo assim são diferentes. É um erro dificílimo de achar a olho nu.

Somando isso a outros motivos práticos (nem todo teclado digita ç com facilidade, programadores de outros países vão ler o código, algumas ferramentas antigas não lidam bem com acentos), a recomendação do guia é: nomes sem acento. Escreva preco, acao, endereco. Acentos ficam dentro dos textos entre aspas, como "Preço: ", onde são bem-vindos.

E o cifrão?

O g++ e o Clang aceitam $ em nomes (int $preco = 5;) como extensão, mas a norma não. O Clang avisa com -pedantic ('$' in identifier [-Wdollar-in-identifier-extension]). Em C++, não use: $ é coisa de PHP e de shell.


Quando dá errado

error: expected unqualified-id before numeric constant

O que significa: o nome começa com algarismo (2lugar).

Como consertar: comece com letra: segundoLugar, lugar2.

error: expected unqualified-id before ‘return’ (ou ‘new’, ‘int’…)

O que significa: você usou uma palavra reservada como nome.

Como consertar: escolha outro nome, de preferência mais descritivo: valorDeRetorno, novoItem, tipoDeConta.

error: expected initializer before ‘-’ token / before ‘palavra’

O que significa: o nome tem hífen ou espaço no meio, e o compilador entendeu duas coisas separadas.

Como consertar: minhaVariavel ou minha_variavel.

error: ‘Nota’ was not declared in this scope; did you mean ‘nota’?

O que significa: o nome existe, mas escrito com outras maiúsculas e minúsculas (ou com uma letra trocada).

Como consertar: aceite a sugestão do compilador ou copie o nome exatamente como na declaração. Se a sugestão parecer idêntica ao que você escreveu, desconfie de acentos (seção 6).


Referência rápida

NomeVale?Por quê
idade, item2SimLetras e algarismos, começando com letra.
precoTotal, preco_totalSimcamelCase e snake_case.
_totalSim, mas eviteComeçar com _ fica perto demais dos nomes reservados.
_Total, __xCompila, mas é reservado_ + maiúscula e __ pertencem ao compilador e à biblioteca.
preço, açãoSim (g++ 15 e Clang 21), mas eviteRisco de dois "ç" invisivelmente diferentes; teclados; leitores de outros países.
2lugarNãoComeça com algarismo.
minha-variavel, minha variavelNãoHífen é "menos"; espaço separa palavras.
int, return, class, newNãoPalavras reservadas.
cout, string, finalCompila, mas eviteNão são palavras-chave, mas confundem o leitor.

Exercícios

1. camelCase

Escreva em camelCase o nome para "nota da prova":

double = 9.5;

2. snake_case

Escreva em snake_case o nome para "total de vendas":

int = 0;

3. Qual destes nomes é válido e segue as recomendações do guia?

4. O programa declara int Total = 10; e depois usa total. O que acontece?

5. Qual destas palavras não é uma palavra-chave do C++?

6. O g++ 15 compila int ação = 3;?

Missão final: rebatize as variáveis

Missão: o programa funciona, mas ninguém entende o que a, b e c guardam. Troque os nomes por quantidade, preco e total (em todos os lugares em que aparecem) e rode. A saída tem que continuar Total: 7.5.

#include <iostream>

int main() {
    int a = 3;
    double b = 2.5;
    double c = a * b;
    std::cout << "Total: " << c << "\n";
}
#include <iostream>

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

Resumo

  • Nome (identificador) = letras, algarismos e _, começando com letra. Sem espaço, hífen ou pontuação.
  • As 92 palavras-chave do C++23 (int, return, class…) não podem ser nomes. cout e string podem, mas não devem.
  • Não comece nomes com _: _Maiuscula e __ são reservados.
  • nota, Nota e NOTA são nomes diferentes. O g++ ajuda com did you mean.
  • Convenções: camelCase (este guia) ou snake_case (a biblioteca padrão); um estilo por projeto.
  • Bons nomes dizem o que a caixa guarda: quantidade, e não a.
  • O g++ 15 aceita int ação, mas evite acentos em nomes: dois "ç" podem parecer iguais e ser diferentes.