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.
- 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
camelCaseesnake_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
- Um nome usa letras, algarismos (0 a 9) e o sublinhado
_. - O primeiro caractere é uma letra ou
_. Nunca um algarismo. - Sem espaços, sem hífen, sem pontuação (
-,.,!,@…). - Não pode ser uma palavra reservada da linguagem (seção 2).
- 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
2lugarcomo o número2seguido de um "sufixo" chamadolugar(sufixos existem, como osde"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.
| Assunto | Palavras-chave | Onde aparecem |
|---|---|---|
| Tipos | bool char char8_t char16_t char32_t wchar_t short int long signed unsigned float double void auto | Tipos de Dados, auto |
| Valores | true false nullptr this | bool, nullptr, this |
| Decisões | if else switch case default | if e else, switch |
| Repetições e saltos | for while do break continue return goto | for, while, break e continue |
| Constantes e armazenamento | const constexpr consteval constinit static extern mutable volatile register thread_local inline | Constantes, constexpr e consteval |
| Tipos próprios e classes | struct class union enum public private protected friend virtual explicit operator typedef using namespace | Structs, Classes |
| Memória | new delete sizeof alignof alignas | new e delete |
| Conversões e tipos | static_cast dynamic_cast const_cast reinterpret_cast typeid decltype | Conversão de Tipos |
| Erros | try catch throw noexcept static_assert | Exceções |
| Templates | template typename concept requires | Templates, Concepts |
| Corrotinas, módulos, outros | co_await co_return co_yield export asm | (avançado; Módulos) |
| Operadores escritos por extenso | and or not xor and_eq or_eq xor_eq not_eq bitand bitor compl | Operadores 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
- "
Notanã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, comnotaembaixo 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:
| Estilo | Exemplo | Como é | Quem usa |
|---|---|---|---|
| camelCase ("caixa de camelo") | precoTotal | Primeira 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_total | Tudo 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. |
| PascalCase | ContaBancaria | Todas as palavras com maiúscula. | Costuma ser reservado para tipos que você cria (structs e classes). |
| MAIÚSCULAS_COM_SUBLINHADO | NOTA_MAXIMA | Tudo 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.
| Ruim | Por quê | Melhor |
|---|---|---|
x, a, n2 | Não diz nada. | idade, alunos |
qtdPrdEst | Abreviação que só o autor entende. | quantidadeEmEstoque |
dados, valor, coisa | Genérico demais: todo valor é um "dado". | notaDaProva, saldo |
numeroDeAlunosMatriculadosNaTurmaDoTerceiroAno | Longo demais para ler e digitar. | alunosTerceiroAno |
l, O, I | Confundem-se com 1 e 0 em muitas fontes. | linha, total |
temp2, teste | Sobras de testes que ficam para sempre. | Um nome que diga o papel da variável. |
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çonão foi declarada; você quis dizerpreç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.
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
| Nome | Vale? | Por quê |
|---|---|---|
idade, item2 | Sim | Letras e algarismos, começando com letra. |
precoTotal, preco_total | Sim | camelCase e snake_case. |
_total | Sim, mas evite | Começar com _ fica perto demais dos nomes reservados. |
_Total, __x | Compila, mas é reservado | _ + maiúscula e __ pertencem ao compilador e à biblioteca. |
preço, ação | Sim (g++ 15 e Clang 21), mas evite | Risco de dois "ç" invisivelmente diferentes; teclados; leitores de outros países. |
2lugar | Não | Começa com algarismo. |
minha-variavel, minha variavel | Não | Hífen é "menos"; espaço separa palavras. |
int, return, class, new | Não | Palavras reservadas. |
cout, string, final | Compila, mas evite | Não são palavras-chave, mas confundem o leitor. |
Exercícios
1. camelCase
Escreva em camelCase o nome para "nota da prova":
2. snake_case
Escreva em snake_case o nome para "total de vendas":
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.coutestringpodem, mas não devem. - Não comece nomes com
_:_Maiusculae__são reservados. nota,NotaeNOTAsão nomes diferentes. O g++ ajuda comdid you mean.- Convenções:
camelCase(este guia) ousnake_case(a biblioteca padrão); um estilo por projeto. - Bons nomes dizem o que a caixa guarda:
quantidade, e nãoa. - O g++ 15 aceita
int ação, mas evite acentos em nomes: dois "ç" podem parecer iguais e ser diferentes.