Eu quero ser melhor em saber quando devo lançar. Quais são as regras implícitas de conversão de tipos em C ++ ao adicionar, multiplicar etc. Por exemplo,
int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?
et cetera ...
A expressão será sempre avaliada como o tipo mais preciso? As regras diferem para Java? Corrija-me se eu tiver formulado esta pergunta incorretamente.
^
é XOR.Respostas:
Em operadores C ++ (para tipos de POD) sempre agem em objetos do mesmo tipo.
Assim, se não forem os mesmos, um será promovido para corresponder ao outro.
O tipo do resultado da operação é o mesmo dos operandos (após a conversão).
Nota. O tamanho mínimo das operações é
int
. Entãoshort
/char
são promovidos aint
antes da operação é feito.Em todas as suas expressões, o valor
int
é promovido afloat
antes de a operação ser executada. O resultado da operação é afloat
.fonte
char
tipo supereficiente . Se o valor dechar + char
for atribuído a achar
, ele poderá fazer a aritméticachar
e, por exemplo, contornar. Mas se o resultado for atribuídoint
, ele deverá fazer a aritmética em um tipo grande o suficiente para obter o resultado correto quando for maior queCHAR_MAX
.((int) 4) - ((unsigned int) 5)
resultará em4294967295
entradas de 32 bits e entradas de sinal de 32 bits.Operações aritméticas envolvendo
float
resultados emfloat
.Para uma resposta mais detalhada. Veja o que diz a seção §5 / 9 do padrão C ++
fonte
double
nemlong double
.long long
eunsigned long
não abordado aqui.float
não possui bits suficientes na mantissa (24 bits para IEEE-754 ) para um de 32 bitsint
; portanto, pode haver perda de dados. Um de 64 bitsdouble
deve estar bem.Como as outras respostas não falam sobre as regras do C ++ 11, aqui está uma. Do padrão C ++ 11 (rascunho n3337) §5 / 9 (enfatizava a diferença):
Veja aqui uma lista atualizada com frequência.
fonte
Esta resposta é direcionada em grande parte a um comentário feito por @ RafałDowgird:
Lembre-se de que o padrão C ++ possui a regra "como se". Consulte a seção 1.8: Execução do programa:
O compilador não pode definir um
int
tamanho de 8 bits, mesmo que seja o mais rápido, pois o padrão exige um mínimo de 16 bitsint
.Portanto, no caso de um computador teórico com operações super rápidas de 8 bits, a promoção implícita
int
para aritmética pode ter importância. No entanto, para muitas operações, você não pode dizer se o compilador realmente fez as operações na precisão de umint
e depois foi convertido em umchar
para armazenar em sua variável, ou se as operações foram realizadas no char o tempo todo.Por exemplo, considere
unsigned char = unsigned char + unsigned char + unsigned char
, onde a adição estouraria (vamos assumir um valor de 200 para cada). Se você promoveu paraint
, obteria 600, que seriam implicitamente convertidos em umunsigned char
, que envolveria o módulo 256, resultando em um resultado final de 88. Se você não realizasse essas promoções, teria que agrupar entre as primeiras duas adições, o que reduziria o problema de200 + 200 + 200
para144 + 200
, que é 344, e reduz para 88. Em outras palavras, o programa não sabe a diferença, portanto o compilador pode ignorar o mandato de executar operações intermediáriasint
se os operandos tiverem uma classificação inferior aint
.Isso é verdade em geral de adição, subtração e multiplicação. Não é verdade em geral para divisão ou módulo.
fonte
Se você excluir os tipos não assinados, haverá uma hierarquia ordenada: char assinado, curto, int, longo, longo, flutuante, duplo, longo duplo. Primeiro, qualquer coisa que venha antes de int acima será convertida em int. Em uma operação binária, o tipo de classificação mais baixa será convertido para o mais alto e os resultados serão do tipo de maior. (Você notará que, a partir da hierarquia, sempre que um ponto flutuante e um tipo integral estiverem envolvidos, o tipo integral será convertido no tipo de ponto flutuante.)
Não assinado complica um pouco as coisas: perturba a classificação e partes da classificação tornam-se definidas para implementação. Por isso, é melhor não combinar assinado e não assinado na mesma expressão. (A maioria dos especialistas em C ++ parece evitar a assinatura, a menos que operações bit a bit estejam envolvidas. Isso é, pelo menos, o que Stroustrup recomenda.)
fonte
int
para um número que nunca precisa ser negativo é um desperdício completo de 50% da faixa disponível. Certamente não sou Stroustrup, mas usounsigned
por padrão esigned
somente quando tenho um motivo.bool in_order(vector<T> vec) { for ( int i = 0; i < size() - 1; ++i) { if (vec[i + 1] < vec[i]) return false; } return true;
e então você estaria irritado ao descobrir que ele trava para vetores vazios porque size () - 1 retorna 18446744073709551615.Minha solução para o problema tem WA (resposta errada), então eu mudei um de
int
paralong long int
e deu AC (aceitar) . Anteriormente, eu estava tentando fazerlong long int += int * int
e depois de corrigi-lolong long int += long long int * int
. Pesquisando no Google,1. Conversões aritméticas
Condições para conversão de tipo:
Condições atendidas ---> Conversão
Qualquer operando é do tipo long double . ---> Outro operando é convertido para o tipo long double .
A condição precedente não foi atendida e qualquer operando é do tipo duplo . ---> Outro operando é convertido para o tipo double .
Condições precedentes não atendidas e qualquer operando é do tipo float . ---> Outro operando é convertido para o tipo float .
Condições precedentes não atendidas (nenhum dos operandos é do tipo flutuante). ---> Promoções integrais são realizadas nos operandos da seguinte maneira:
2) Regras de conversão de número inteiro
Tipos inteiros menores que int são promovidos quando uma operação é executada neles. Se todos os valores do tipo original puderem ser representados como um int, o valor do tipo menor será convertido em um int; caso contrário, é convertido em um int sem sinal. Promoções inteiras são aplicadas como parte das conversões aritméticas usuais em certas expressões de argumento; operandos dos operadores +, - e ~ unários; e operandos dos operadores de turno.
Classificação de conversão de número inteiro:
long long int
deve ser maior que a classificação delong int
, que deve ser maior que a classificação deint
, que deve ser maior que a classificação deshort int
, que deve ser maior que a classificação designed char
.char
será igual à classificação designed char
eunsigned char
.Conversões aritméticas comuns:
fonte
Todo o capítulo 4 fala sobre conversões, mas acho que você deve se interessar principalmente por estas:
4.5 Promoções integrais [conv.prom]
Um rvalor do tipo char, assinado, char não assinado, short int ou short curto não assinado pode ser convertido em um rvalor do tipo int se int puder representar todos os valores do tipo de origem; caso
contrário, o rvalue de origem pode ser convertido em um rvalue do tipo unsigned int.
Um rvalue do tipo wchar_t (3.9.1) ou um tipo de enumeração (7.2) pode ser convertido em um rvalue do primeiro
dos seguintes tipos que podem representar todos os valores do seu tipo subjacente: int, sem sinal int,
longo ou sem sinal longo.
Um rvalue para um campo de bits integral (9.6) pode ser convertido em um rvalue do tipo int se int puder representar todos
os valores do campo de bits; caso contrário, ele pode ser convertido em unsigned int se int não assinado puder
reenviar todos os valores do campo de bits. Se o campo de bits ainda for maior, nenhuma promoção integral se aplicará a ele. Se o
campo de bits tiver um tipo enumerado, será tratado como qualquer outro valor desse tipo para fins de promoção.
Um rvalue do tipo bool pode ser convertido em um rvalue do tipo int, com false se tornando zero e true
se tornando um.
Essas conversões são chamadas de promoções integrais.
4.6 Promoção de ponto flutuante [conv.fpprom]
Um rvalue do tipo float pode ser convertido em um rvalue do tipo double. O valor é inalterado.
Essa conversão é chamada de promoção de ponto flutuante.
Portanto, todas as conversões envolvendo float - o resultado é float.
Somente o que envolve os dois int - o resultado é int: int / int = int
fonte
O tipo da expressão, quando as duas partes não forem do mesmo tipo, será convertido na maior das duas. O problema aqui é entender qual é maior que o outro (não tem nada a ver com tamanho em bytes).
Nas expressões em que um número real e um número inteiro estão envolvidos, o número inteiro será promovido para um número real. Por exemplo, em int + float, o tipo da expressão é float.
A outra diferença está relacionada à capacidade do tipo. Por exemplo, uma expressão envolvendo int e long int resultará do tipo long int.
fonte
long
é "maior" que afloat
mas qual é o tipo delong
+float
?Embargo!
As conversões ocorrem da esquerda para a direita.
Tente o seguinte:
fonte
j + i * k
resultaria em 101.