C++ Conversão de Tipos
Em C++, todo valor tem um tipo: 7 é um int, 9.99 é um double, 'A' é um char. Muitas vezes você precisa usar um valor de um tipo onde se espera outro: guardar um preço com centavos numa variável de números inteiros, calcular a média de notas inteiras com vírgula, descobrir o código de uma letra. Essa passagem de um tipo para outro se chama conversão. Às vezes o C++ a faz sozinho, sem avisar nada; às vezes você precisa pedir. Nesta aula você vai ver as duas formas e as armadilhas de cada uma.
- O que é conversão implícita (automática):
int→doublenão perde nada;double→intcorta a parte depois do ponto. - Como pedir ao g++ que avise dessas perdas com
-Wconversion. - Como converter de propósito com
static_cast<T>(valor). - Por que
7 / 2dá3, e como obter3.5. - O que é o cast "estilo C"
(int)xe por que preferirstatic_cast. - Como passar de
charparainte de volta.
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 (veja Compilar com g++). Você pode repetir cada um no editor do guia, que compila C++ de verdade no navegador.
A ideia: passar água de um copo para outro
Imagine dois recipientes na cozinha da Ana: uma jarra grande, com marcações de meio em meio copo, e uma forminha de gelo, em que cada buraco guarda uma porção inteira, sem frações.
- Passar da forminha para a jarra é tranquilo: 7 porções inteiras viram "7,0" na jarra. Nada se perde.
- Passar da jarra para a forminha é diferente: se a jarra tem "9,99", só cabem 9 porções inteiras. O "0,99" que sobrou vai para a pia. Ninguém arredonda para 10.
No C++, o int é a forminha (só números inteiros, veja Inteiros) e o double é a jarra (números com parte fracionária, veja float e double). Toda conversão é uma dessas duas situações: ou o valor cabe no tipo novo, ou alguma coisa se perde.
1. Conversão implícita: o C++ converte sozinho
"Implícita" quer dizer "sem ninguém pedir". Sempre que você coloca um valor de um tipo numa variável de outro tipo, o C++ tenta converter automaticamente. Veja os dois sentidos no mesmo programa:
#include <iostream>
int main() {
int caixas = 7;
double total = caixas; // int vira double
std::cout << total << '\n';
std::cout << total / 2 << '\n';
double preco = 9.99;
int reais = preco; // double vira int: corta
std::cout << reais << '\n';
double temperatura = -2.7;
int t = temperatura;
std::cout << t << '\n';
}
- double total = caixas;
- O lado direito é um
int(7). A variável édouble. O C++ converte o 7 em 7.0 e guarda. Isso se chama conversão de alargamento: o tipo novo é "maior", tudo cabe. - total / 2
- Como
totalédouble, a divisão é feita com vírgula: 7.0 / 2 = 3.5. - int reais = preco;
- O lado direito é
double(9.99); a variável éint. O C++ joga fora tudo depois do ponto. Isso é uma conversão de estreitamento (em inglês, narrowing): o tipo novo é "menor". - int t = temperatura;
- Com números negativos, o corte também vai em direção ao zero: −2.7 vira −2 (e não −3).
$ g++ -std=c++23 -Wall -Wextra implicita.cpp -o implicita $ ./implicita 7 « o double 7.0 aparece sem o ".0": o cout esconde zeros que não mudam o valor 3.5 9 « 9.99 virou 9: os 99 centavos foram para a pia -2 « -2.7 virou -2: corta em direção ao zero
Repare no detalhe mais importante: o g++ compilou sem nenhum aviso, mesmo com -Wall -Wextra. Para ele, cortar 9.99 em 9 é uma operação legal, que você pode ter feito de propósito. Os 99 centavos sumiram em silêncio.
A conversão de double para int sempre corta (os matemáticos dizem "trunca"): 9.99 vira 9, 9.5 vira 9, 9.01 vira 9. Se você quer arredondar, use std::round, mostrado mais abaixo nesta aula.
Pedindo o aviso: -Wconversion
O g++ tem uma opção que não faz parte do -Wall nem do -Wextra: -Wconversion ("avisar sobre conversões"). Com ela, toda conversão que pode mudar o valor vira um aviso. É o mesmo programa, compilado de novo com a opção a mais:
$ g++ -std=c++23 -Wall -Wextra -Wconversion implicita.cpp -o implicita
implicita.cpp: In function ‘int main()’:
implicita.cpp:10:17: warning: conversion from ‘double’ to ‘int’ may change value [-Wfloat-conversion]
10 | int reais = preco; // double vira int: corta
| ^~~~~
implicita.cpp:14:13: warning: conversion from ‘double’ to ‘int’ may change value [-Wfloat-conversion]
14 | int t = temperatura;
| ^~~~~~~~~~~
Leia o aviso por partes (a aula Lendo Erros do Compilador explica o formato):
| Pedaço | O que quer dizer |
|---|---|
implicita.cpp:10:17 | Arquivo, linha 10, coluna 17: onde está o problema. |
warning: | É um aviso, não um erro: o programa foi gerado mesmo assim. |
conversion from ‘double’ to ‘int’ may change value | "A conversão de double para int pode mudar o valor." |
[-Wfloat-conversion] | O nome do tipo de aviso. -Wfloat-conversion (conversões com números de ponto flutuante) é uma parte do -Wconversion. |
Repare que a linha 5 (double total = caixas;) não foi avisada: de int para double o valor nunca muda. O aviso aparece só onde pode haver perda.
Em programas pequenos, como os deste guia, sim: -Wconversion pega exatamente o tipo de engano que esta aula ensina. Em projetos grandes ele pode avisar demais, e muita gente liga só em partes do código. A aula Avisos (-Wall -Wextra) mostra outras opções úteis. O comando padrão do guia continua sendo -Wall -Wextra; quando usarmos -Wconversion, ele vai aparecer escrito.
Outros estreitamentos silenciosos
Não é só a parte fracionária que se perde. Um número grande demais para o tipo novo também é "estragado" em silêncio:
#include <iostream>
int main() {
long long populacao = 5000000000;
int p = populacao;
std::cout << p << '\n';
int negativo = -1;
unsigned int u = negativo;
std::cout << u << '\n';
}
$ g++ -std=c++23 -Wall -Wextra grande.cpp -o grande
$ ./grande
705032704 « cinco bilhões não cabem num int: sobrou um número sem sentido
4294967295 « -1 num unsigned (sem sinal) vira o maior unsigned int
$ g++ -std=c++23 -Wall -Wextra -Wconversion grande.cpp -o grande
grande.cpp: In function ‘int main()’:
grande.cpp:5:13: warning: conversion from ‘long long int’ to ‘int’ may change value [-Wconversion]
5 | int p = populacao;
| ^~~~~~~~~
Um int vai só até 2.147.483.647 (veja Inteiros). O que passa disso "dá a volta" e vira outro número. Já o −1 dentro de um unsigned int (um inteiro que não tem sinal, só aceita 0 e positivos) vira 4294967295. Esse comportamento volta a aparecer, de forma bem mais traiçoeira, na aula Operadores de Comparação. O aviso de int para unsigned tem nome próprio, -Wsign-conversion, e não vem nem com o -Wconversion.
As chaves pegam o estreitamento
Na aula Variáveis você viu que dá para inicializar com chaves: int x{5};. Uma das vantagens das chaves é exatamente esta: elas não aceitam estreitamento.
#include <iostream>
int main() {
double preco = 9.99;
int reais{preco};
std::cout << reais << '\n';
}
$ g++ -std=c++23 -Wall -Wextra estreita.cpp -o estreita
estreita.cpp: In function ‘int main()’:
estreita.cpp:5:15: warning: narrowing conversion of ‘preco’ from ‘double’ to ‘int’ [-Wnarrowing]
5 | int reais{preco};
| ^~~~~
"Conversão de estreitamento de preco, de double para int." Aqui o g++ dá só um aviso, sem precisar de -Wconversion. Se o valor for escrito direto, como int reais{9.99};, o g++ recusa de vez:
$ g++ -std=c++23 -Wall -Wextra estreita2.cpp -o estreita2
estreita2.cpp: In function ‘int main()’:
estreita2.cpp:4:15: error: narrowing conversion of ‘9.9900000000000002e+0’ from ‘double’ to ‘int’ [-Wnarrowing]
4 | int reais{9.99};
| ^~~~
(O 9.9900000000000002e+0 é o 9.99 do jeito que ele fica guardado na memória: double quase nunca guarda o número exato. A aula float e double explica.) No editor do guia, que usa o Clang, os dois casos são erro: type 'double' cannot be narrowed to 'int' in initializer list.
Experimente: rode o programa e veja os cortes. Depois troque 8.75 por 8.999 e por -8.999. Por fim, troque int a = nota; por int a{nota}; e veja o compilador recusar.
#include <iostream>
int main() {
double nota = 8.75;
int a = nota;
std::cout << "nota (double): " << nota << '\n';
std::cout << "a (int): " << a << '\n';
}
2. Conversão explícita com static_cast
Quando a conversão é de propósito, diga isso no código. A ferramenta do C++ para isso é o static_cast ("conversão estática", ou seja, decidida na hora de compilar). Uma conversão pedida por você se chama explícita, ou um cast (em inglês, "moldar": você coloca o valor num molde de outro tipo).
#include <iostream>
int main() {
double preco = 9.99;
int a = static_cast<int>(preco); // C++: o jeito recomendado
int b = (int)preco; // estilo C
int c = int(preco); // estilo "função"
std::cout << a << ' ' << b << ' ' << c << '\n';
}
- static_cast
- A palavra que pede a conversão. É uma palavra reservada do C++, não precisa de
#include. - <int>
- Entre os sinais de menor e maior, o tipo de destino: "converta para
int". - (preco)
- Entre parênteses, o valor que será convertido. Pode ser uma variável, um número ou uma conta inteira:
static_cast<int>(preco * 100). - (int)preco e int(preco)
- Outras duas formas de escrever a mesma conversão. Você vai entender a diferença na seção 4.
$ g++ -std=c++23 -Wall -Wextra -Wconversion cast.cpp -o cast $ ./cast 9 9 9
O resultado é o mesmo corte (9), mas agora nem com -Wconversion aparece aviso. É como assinar embaixo: "eu sei que vou perder os centavos e é isso que eu quero". Quem lê o código também entende na hora que a perda foi de propósito.
E se eu quiser arredondar?
O static_cast só corta. Para arredondar, use std::round da biblioteca <cmath> (a aula Matemática (cmath) mostra todas as funções). Ele arredonda para o inteiro mais próximo e devolve um double; se você precisar de um int, converta o resultado:
#include <cmath>
#include <iostream>
int main() {
double preco = 9.99;
std::cout << static_cast<int>(preco) << '\n';
std::cout << std::round(preco) << '\n';
std::cout << static_cast<int>(std::round(preco)) << '\n';
std::cout << std::lround(-2.7) << '\n';
}
$ g++ -std=c++23 -Wall -Wextra arredondar.cpp -o arredondar $ ./arredondar 9 « static_cast: corta 10 « std::round: arredonda (resultado double) 10 « arredonda e depois converte para int -3 « std::lround arredonda e já devolve um inteiro (long)
3. Divisão inteira × divisão real
Esta é a conversão que mais engana quem começa. Em C++, o tipo do resultado de uma conta depende do tipo dos números da conta, e não da variável onde você vai guardar o resultado.
- Se os dois lados da divisão são
int, a divisão é inteira: o resultado é umint, e a parte fracionária é cortada. - Se pelo menos um lado é
double, o outro é convertido paradoubleautomaticamente (é uma conversão implícita), e a divisão é real.
#include <iostream>
int main() {
std::cout << 7 / 2 << '\n';
std::cout << 7 / 2.0 << '\n';
std::cout << 7.0 / 2 << '\n';
std::cout << static_cast<double>(7) / 2 << '\n';
std::cout << static_cast<double>(7 / 2) << '\n';
}
$ g++ -std=c++23 -Wall -Wextra divisao.cpp -o divisao $ ./divisao 3 3.5 3.5 3.5 3
| Expressão | Tipos | Resultado | Por quê |
|---|---|---|---|
7 / 2 | int / int | 3 | Divisão inteira: 3,5 é cortado para 3. |
7 / 2.0 | int / double | 3.5 | O 2.0 é double, então o 7 vira 7.0. |
7.0 / 2 | double / int | 3.5 | Basta um dos lados ser double. |
static_cast<double>(7) / 2 | double / int | 3.5 | O cast transforma o 7 em 7.0 antes da divisão. |
static_cast<double>(7 / 2) | double( int / int ) | 3 | Armadilha: os parênteses fazem a divisão inteira primeiro (dá 3), e só depois o 3 vira 3.0. Tarde demais. |
Com números escritos direto no código, basta colocar .0. Mas com variáveis int não dá para "colocar .0": é aí que o static_cast é indispensável. O caso clássico é a média de notas:
#include <iostream>
int main() {
int soma = 17; // 8 + 9
int provas = 2;
double media_errada = soma / provas;
double media = static_cast<double>(soma) / provas;
std::cout << "Errada: " << media_errada << '\n';
std::cout << "Certa: " << media << '\n';
}
$ g++ -std=c++23 -Wall -Wextra media.cpp -o media $ ./media Errada: 8 Certa: 8.5
soma / provas: os dois sãoint, então a conta é inteira: 17 / 2 = 8 (o 0,5 se perde aqui).double media_errada = 8;: o 8 vira 8.0, mas a metade já foi embora no passo anterior. A variável serdoublenão ajuda.static_cast<double>(soma): o 17 vira 17.0 antes da divisão.17.0 / provas: um lado é double, então o 2 vira 2.0 e a conta é real: 8.5.
O g++ não avisa nada, nem com -Wconversion, porque nenhuma conversão perdeu valor: quem "perdeu" foi a divisão inteira, que é uma operação legítima. A aula Operadores Aritméticos mostra a divisão inteira com mais detalhes, incluindo o resto (%).
Missão: o programa calcula a média de 4 notas, mas mostra Média: 7. Corrija a linha da média com static_cast<double> para aparecer Média: 7.5.
#include <iostream>
int main() {
int n1 = 7;
int n2 = 8;
int n3 = 6;
int n4 = 9;
int soma = n1 + n2 + n3 + n4;
double media = soma / 4;
std::cout << "Média: " << media << '\n';
}
#include <iostream>
int main() {
int n1 = 7;
int n2 = 8;
int n3 = 6;
int n4 = 9;
int soma = n1 + n2 + n3 + n4;
double media = static_cast<double>(soma) / 4;
std::cout << "Média: " << media << '\n';
}
4. O cast estilo C: (int)x
O C++ nasceu do C (veja O que é C++), e o C tem uma forma curta de converter: o tipo entre parênteses antes do valor, (int)preco. O C++ aceita, e também aceita a forma int(preco), que parece uma função. Você vai ver as duas em código antigo e na internet. No programa cast.cpp acima, as três formas deram 9.
Então qual é o problema? O cast estilo C é poderoso demais. O static_cast só faz conversões que fazem sentido (número para número, por exemplo) e recusa as absurdas. O cast estilo C tenta todas as conversões possíveis, inclusive as perigosas, até achar uma que funcione. Compare os dois tentando transformar o texto "29" em número:
$ cat texto2.cpp
#include <iostream>
int main() {
int idade = static_cast<int>("29");
std::cout << idade << '\n';
}
$ g++ -std=c++23 -Wall -Wextra texto2.cpp -o texto2
texto2.cpp: In function ‘int main()’:
texto2.cpp:4:17: error: invalid ‘static_cast’ from type ‘const char [3]’ to type ‘int’
4 | int idade = static_cast<int>("29");
| ^~~~~~~~~~~~~~~~~~~~~~
O static_cast recusou: "static_cast inválido do tipo const char [3] (um texto de 3 caracteres: 2, 9 e o terminador) para o tipo int". Ótimo: o erro aparece na hora de compilar. Agora o mesmo pedido com o cast estilo C (usando long, um inteiro maior):
$ cat perigo.cpp
#include <iostream>
int main() {
long idade = (long)"29";
std::cout << idade << '\n';
}
$ g++ -std=c++23 -Wall -Wextra perigo.cpp -o perigo
$ ./perigo
104665125543940 « não é 29!
$ ./perigo
97150230274052 « e muda a cada execução
Compilou sem nenhum aviso e mostrou um número enorme, diferente a cada vez. Esse número é o endereço na memória onde o texto "29" está guardado (você vai entender endereços na aula Ponteiros). O cast estilo C fez uma conversão que não tem nada a ver com "texto para número", e ficou quieto. Esse é o motivo de preferir static_cast: ele é mais fácil de achar no código (procure por _cast) e recusa o que não faz sentido.
Se você quiser que o g++ aponte os casts estilo C no seu código, existe o aviso -Wold-style-cast ("cast à moda antiga"). Ele até sugere a troca:
$ g++ -std=c++23 -Wall -Wextra -Wold-style-cast cast.cpp -o cast
cast.cpp: In function ‘int main()’:
cast.cpp:6:18: warning: use of old-style cast to ‘int’ [-Wold-style-cast]
6 | int b = (int)preco; // estilo C
| ^~~~~
| ----------
| static_cast<int> (preco)
_cast
O C++ tem mais três: const_cast, reinterpret_cast e dynamic_cast. Eles servem para situações bem específicas com ponteiros e classes, que aparecem nos níveis 2 e 3 (por exemplo, Polimorfismo). No dia a dia, com números, só o static_cast interessa.
5. char ↔ int: letras são números
Na aula Caracteres (char) você viu que um char guarda um número: o código da letra na tabela ASCII. O 'A' é 65, o 'B' é 66, o 'a' é 97, e o caractere '0' é 48 (não zero!). Por isso, converter entre char e int é natural:
#include <iostream>
int main() {
char letra = 'A';
int codigo = letra; // char vira int
std::cout << codigo << '\n';
std::cout << letra + 1 << '\n'; // a conta é feita em int
std::cout << static_cast<char>(letra + 1) << '\n';
char digito = '7';
int valor = digito - '0'; // '7' (55) - '0' (48)
std::cout << valor << '\n';
std::cout << static_cast<int>(digito) << '\n';
}
$ g++ -std=c++23 -Wall -Wextra letras.cpp -o letras $ ./letras 65 « o código do 'A' 66 « 'A' + 1: o char virou int para a conta, e o cout mostra o número B « convertendo 66 de volta para char, o cout mostra a letra 7 « '7' - '0' = 55 - 48 = 7: o algarismo como número 55 « o código do caractere '7'
- int codigo = letra;
- Conversão implícita de alargamento: todo
charcabe numint. - letra + 1
- Em contas, o C++ converte o
charparaintantes de calcular (isso se chama promoção). O resultado éint, e ocoutmostraintcomo número. - static_cast<char>(letra + 1)
- Para ver a letra, converta de volta para
char. Ocoutdecide como mostrar pelo tipo:charaparece como letra,intcomo número. - digito - '0'
- Os algarismos
'0'a'9'ficam em sequência na tabela (48 a 57). Subtrair'0'dá o valor do algarismo. Esse truque é muito usado para ler números caractere por caractere.
digito - '0' converte um algarismo. Para converter um texto inteiro, como "2026", para número, existem funções próprias (std::stoi e companhia), assunto da aula Texto ↔ Número. E letras com acento ('é', 'ç') não cabem num único char: veja Acentos e UTF-8.
bool ↔ int
O bool (veja Booleanos) também conversa com números: true vira 1 e false vira 0; no sentido contrário, zero vira false e qualquer outro número vira true.
#include <iostream>
int main() {
bool ligado = true;
int n = ligado;
std::cout << n << '\n';
int pontos = 5;
bool tem_pontos = pontos;
std::cout << tem_pontos << '\n';
bool vazio = 0;
std::cout << vazio << '\n';
}
$ g++ -std=c++23 -Wall -Wextra booleano.cpp -o booleano $ ./booleano 1 « true vira 1 1 « 5 é diferente de zero: vira true, que o cout mostra como 1 0 « 0 vira false
Experimente: troque a letra 'C' por outras ('a', 'Z', '!') e veja o código de cada uma. Depois mude o + 2 para andar mais letras.
#include <iostream>
int main() {
char letra = 'C';
std::cout << "Letra: " << letra << '\n';
std::cout << "Código: " << static_cast<int>(letra) << '\n';
std::cout << "Duas letras depois: " << static_cast<char>(letra + 2) << '\n';
}
6. Texto não é número (e cast não resolve)
Um engano comum: achar que "29" (entre aspas) e 29 são a mesma coisa. Não são. "29" é um texto com os caracteres 2 e 9. Nenhum cast transforma texto em número:
$ cat texto.cpp
#include <iostream>
int main() {
int idade = "29";
std::cout << idade << '\n';
}
$ g++ -std=c++23 -Wall -Wextra texto.cpp -o texto
texto.cpp: In function ‘int main()’:
texto.cpp:4:17: error: invalid conversion from ‘const char*’ to ‘int’ [-fpermissive]
4 | int idade = "29";
| ^~~~
| |
| const char*
"Conversão inválida de const char* para int." Para o C++, um texto entre aspas vira um const char*, o endereço de memória onde o texto começa (a setinha embaixo mostra esse tipo). O [-fpermissive] no fim diz que existe uma opção para o g++ "deixar passar", mas não use: o resultado seria o endereço de memória, como no perigo.cpp. Para converter texto em número de verdade, veja Texto ↔ Número.
Formas diferentes: qual usar
| Forma | Exemplo | Quando usar |
|---|---|---|
| Implícita, sem perda | double d = 7; | À vontade: int → double, char → int nunca perdem nada. |
| Implícita, com perda | int r = 9.99; | Evite: a perda fica escondida. Ligue -Wconversion para achar esses lugares. |
| Inicialização com chaves | int r{9.99}; | Use chaves para o compilador recusar estreitamentos sem querer. |
static_cast | static_cast<int>(9.99) | Sempre que a conversão é de propósito. É o padrão deste guia. |
| Cast estilo C | (int)9.99 | Só para entender código antigo. Não escreva código novo assim. |
| Estilo função | int(9.99) | Igual ao estilo C em poder. Também evite. |
std::round / std::lround | std::lround(9.99) | Quando você quer arredondar, não cortar. |
Quando dá errado
$ ./media Errada: 8 « a média sem static_cast Certa: 8.5
O que aconteceu: a divisão soma / provas foi feita entre dois int, então foi inteira. Guardar o resultado num double não recupera o que já foi cortado. Nenhum compilador avisa, porque a divisão inteira é uma operação válida.
Como resolver: converta um dos lados antes da divisão: static_cast<double>(soma) / provas. Cuidado para não escrever static_cast<double>(soma / provas), que converte depois.
error: invalid conversion from ‘const char*’ to ‘int’
O que aconteceu: você tentou guardar um texto entre aspas ("29") numa variável numérica.
Como resolver: se o valor é fixo, tire as aspas: int idade = 29;. Se o texto vem de fora (do teclado, de um arquivo), use std::stoi, da aula Texto ↔ Número. Não "resolva" com (int) ou (long): compila, mas o valor é um endereço de memória.
error: narrowing conversion of … from ‘double’ to ‘int’
O que aconteceu: você inicializou com chaves (int x{9.99};) um valor que não cabe no tipo sem perder parte dele. As chaves foram feitas justamente para impedir isso.
Como resolver: decida o que você quer. Se a variável deveria guardar a parte fracionária, troque o tipo para double. Se você quer mesmo cortar, diga isso: int x{static_cast<int>(9.99)};.
705032704)
O que aconteceu: um valor de um tipo maior (long long) foi colocado num tipo menor (int), e não coube. O g++ só avisa com -Wconversion.
Como resolver: use um tipo que comporte o valor (long long, veja Inteiros) e compile com -Wconversion para achar outros pontos parecidos.
Referência
| De → para | Automático? | O que acontece | Exemplo |
|---|---|---|---|
int → double | Sim | Ganha .0, nada se perde. | 7 → 7.0 |
double → int | Sim, em silêncio | Corta em direção ao zero. | 9.99 → 9, -2.7 → -2 |
long long → int | Sim, em silêncio | Se não couber, vira outro número. | 5000000000 → 705032704 |
int → unsigned | Sim, em silêncio | Negativos viram números enormes. | -1 → 4294967295 |
char → int | Sim | Dá o código da tabela ASCII. | 'A' → 65 |
int → char | Sim | Dá o caractere daquele código. | 66 → 'B' |
bool → int | Sim | true → 1, false → 0. | |
número → bool | Sim | 0 → false; qualquer outro → true. | 5 → true |
| texto → número | Não | Erro de compilação. Use std::stoi. | Texto ↔ Número |
| Opção do g++ | O que avisa |
|---|---|
-Wconversion | Conversões implícitas que podem mudar o valor (inclui -Wfloat-conversion). |
-Wsign-conversion | Conversões entre tipos com e sem sinal. |
-Wold-style-cast | Casts estilo C, (int)x. |
-Wnarrowing | Estreitamento dentro de chaves (já vem ligado). |
Exercícios
1. Converta de propósito
Complete para guardar em inteiro só a parte inteira de altura, do jeito recomendado pelo C++:
2. Divisão real
total e pessoas são int. Complete para a divisão ser real (com vírgula), convertendo o total:
3. Do algarismo ao número
A variável c guarda o caractere '4'. Complete para n valer o número 4:
4. O que std::cout << static_cast<double>(9 / 2); mostra?
5. int x = -7.9; — quanto vale x?
6. Por que preferir static_cast<int>(x) a (int)x?
Missão final: a conta do restaurante
Missão: a conta deu 183 reais, inteiros, para 4 pessoas. Calcule quanto cada um paga, com centavos, usando static_cast<double>. Depois mostre quantas notas de 1 real inteiras isso dá, usando static_cast<int> no valor de cada um. A saída deve ser:
Cada um paga: 45.75 Em notas de 1 real: 45
#include <iostream>
int main() {
int conta = 183;
int pessoas = 4;
// calcule "cada" (double) e "notas" (int) aqui
}
#include <iostream>
int main() {
int conta = 183;
int pessoas = 4;
double cada = static_cast<double>(conta) / pessoas;
int notas = static_cast<int>(cada);
std::cout << "Cada um paga: " << cada << '\n';
std::cout << "Em notas de 1 real: " << notas << '\n';
}
Resumo
- Conversão implícita: o C++ converte sozinho.
int→doublenão perde nada;double→intcorta em direção ao zero, sem aviso. -Wconversionfaz o g++ avisar das conversões que podem mudar o valor. Inicializar com chaves (int x{…}) recusa o estreitamento.- Conversão explícita:
static_cast<tipo>(valor). Use sempre que a conversão for de propósito. int / inté divisão inteira (7 / 2= 3). Para ter3.5, um dos lados precisa serdoubleantes da conta:7 / 2.0oustatic_cast<double>(a) / b.- Cortar não é arredondar: para arredondar,
std::round/std::lround. - O cast estilo C
(int)xexiste, mas aceita conversões absurdas em silêncio. Prefirastatic_cast. charé um número:'A'é 65;'7' - '0'é 7;static_cast<char>(66)é'B'.- Texto (
"29") não vira número com cast: veja Texto ↔ Número.