-2147483648 é o menor número inteiro para o tipo inteiro com 32 bits, mas parece que ele transbordará na if(...)
frase:
if (-2147483648 > 0)
std::cout << "true";
else
std::cout << "false";
Isso será impresso true
nos meus testes. No entanto, se convertermos -2147483648 em número inteiro, o resultado será diferente:
if (int(-2147483648) > 0)
std::cout << "true";
else
std::cout << "false";
Isso será impresso false
.
Estou confuso. Alguém pode dar uma explicação sobre isso?
Atualização 02-05-2012:
Obrigado pelos seus comentários, no meu compilador, o tamanho de int é 4 bytes. Estou usando o VC para alguns testes simples. Eu mudei a descrição na minha pergunta.
São muitas respostas muito boas neste post, o AndreyT deu uma explicação muito detalhada sobre como o compilador se comportará em tais entradas e como esse número inteiro mínimo foi implementado. O qPCR4vir, por outro lado, forneceu algumas "curiosidades" relacionadas e como o número inteiro é representado. Tão impressionante!
fonte
INT_MIN
de-9223372036854775808
, seCHAR_BIT
for 16. E mesmo comCHAR_BIT == 8
esizeof(int
== 4) `você pode obter-9223372036854775807
porque C não requer números de 2 complementos.Respostas:
-2147483648
não é um "número". A linguagem C ++ não suporta valores literais negativos.-2147483648
é na verdade uma expressão: um valor literal positivo2147483648
com um-
operador unário à sua frente. O valor2147483648
é aparentemente muito alto para o lado positivo doint
intervalo na sua plataforma. Se o tipolong int
tivesse maior alcance em sua plataforma, o compilador teria que assumir automaticamente que2147483648
possui olong int
tipo. (No C ++ 11, o compilador também precisaria considerar olong long int
tipo.) Isso faria o compilador avaliar-2147483648
no domínio de tipo maior e o resultado seria negativo, como seria de esperar.No entanto, aparentemente no seu caso, o intervalo de
long int
é igual ao intervalo deint
e, em geral, não existe um tipo inteiro com maior alcance do queint
na sua plataforma. Isso significa formalmente que a constante positiva2147483648
excede todos os tipos de números inteiros assinados disponíveis, o que, por sua vez, significa que o comportamento do seu programa é indefinido. (É um pouco estranho que a especificação da linguagem opte por comportamentos indefinidos nesses casos, em vez de exigir uma mensagem de diagnóstico, mas é assim que acontece.)Na prática, levando em conta que o comportamento é indefinido,
2147483648
pode ser interpretado como um valor negativo dependente da implementação que, por acaso, se torna positivo após a-
aplicação unária a ele. Como alternativa, algumas implementações podem decidir tentar usar tipos não assinados para representar o valor (por exemplo, em compiladores C89 / 90 eram necessáriosunsigned long int
, mas não em C99 ou C ++). As implementações têm permissão para fazer qualquer coisa, pois o comportamento é indefinido de qualquer maneira.Como uma observação lateral, esta é a razão pela qual constantes como
INT_MIN
são tipicamente definidas comoem vez do aparentemente mais direto
Este último não funcionaria como pretendido.
fonte
#define INT_MIN (-2147483647 - 1)
.int
. A implementação do OP pode não ter um tipo de 64 bits.-1.0
seja analisado como um valor duplo negativo, não é?unsigned long int
nesse contexto, mas no C99 essa permissão foi removida. Literais não substituídos em C e C ++ devem ter tipos assinados . Se você vir um tipo não assinado aqui quando um assinado funcionaria, significa que seu compilador está quebrado. Se você vir um tipo não assinado aqui, quando nenhum tipo assinado funcionaria, isso é apenas uma manifestação específica de comportamento indefinido.O compilador (VC2012) promove os números "mínimos" que podem conter os valores. No primeiro caso,
signed int
(elong int
) não pode (antes da aplicação do sinal), masunsigned int
pode:2147483648
hasunsigned int
???? tipo. No segundo você força aint
partir dounsigned
.Aqui estão relacionadas "curiosidades":
Padrão C ++ 11 :
...
...
E estas são as regras de promoções para números inteiros no padrão.
fonte
int
,long int
,unsigned long int
para representar constantes decimais unsuffixed. Esse era o único idioma que permitia o uso de tipos não assinados para constantes decimais não substituídas. No C ++ 98, eraint
oulong int
. Não são permitidos tipos não assinados. Nem C (iniciando em C99) nem C ++ permitem que o compilador use tipos não assinados nesse contexto. Obviamente, seu compilador é livre para usar tipos não assinados, se nenhum dos assinados funcionar, mas isso ainda é apenas uma manifestação específica de comportamento indefinido.int
ou outrolong int
para representar2147483648
. Além disso, AFAIK, em VC2012 tantoint
elong int
são tipos de 32 bits. Isso significa que, no VC2012, o literal2147483648
deve levar a um comportamento indefinido . Quando o comportamento é indefinido, o compilador pode fazer qualquer coisa. Isso significaria que o VC2012 não está quebrado. Simplesmente emitiu uma mensagem de diagnóstico enganosa. Em vez de dizer que o comportamento é indefinido, ele decidiu usar um tipo não assinado.long
e não seja necessário emitir um diagnóstico? Isso parece quebrado.Em suma,
2147483648
transborda para-2147483648
e(-(-2147483648) > 0)
étrue
.Isto é como
2147483648
parece em binário.Além disso, no caso de cálculos binários assinados, o bit mais significativo ("MSB") é o bit de sinal. Esta pergunta pode ajudar a explicar o porquê.
fonte
Como
-2147483648
na verdade se aplica2147483648
negation (-
), o número não é o que você esperaria. Na verdade, é o equivalente a esse pseudocódigo:operator -(2147483648)
Agora, assumindo que o seu compilador tem
sizeof(int)
igual4
eCHAR_BIT
é definido como8
, que faria2147483648
transbordar o valor máximo assinado de um inteiro (2147483647
). Então, qual é o máximo mais um? Vamos resolver isso com um número inteiro de 4 bits e 2s.Esperar! 8 excede o número inteiro! O que nós fazemos? Use sua representação não assinada
1000
e interprete os bits como um número inteiro assinado. Essa representação nos deixa com-8
a aplicação da negação do complemento 2s resultando em8
, que, como todos sabemos, é maior que0
.É por isso que
<limits.h>
(e<climits>
) geralmente definemINT_MIN
como((-2147483647) - 1)
- para que o número máximo máximo assinado (0x7FFFFFFF
) seja negado (0x80000001
) e depois decrementado (0x80000000
).fonte
-8
ainda é-8
.-(8)
que em C ++ é o mesmo que-8
- é negação aplicada a um literal, não um literal negativo. O literal é8
, que não se encaixa em um número inteiro de 4 bits assinado, portanto deve ser não assinado. O padrão é1000
. Até agora, sua resposta está correta. A negação do complemento dos dois1000
em 4 bits é1000
que não importa se está assinado ou não. Sua resposta diz: "interprete os bits como um número inteiro assinado", que cria o valor-8
após a negação do complemento dos dois, exatamente como era antes da negação.8
. A negação é aplicada (módulo 16), resultando em uma resposta final de8
. A codificação ainda é 1000, mas o valor é diferente porque um tipo não assinado foi escolhido.