-2147483648 es el número entero más pequeño para el tipo entero con 32 bits, pero parece que se desbordará en la if(...)oración:
if (-2147483648 > 0)
std::cout << "true";
else
std::cout << "false";
Esto se imprimirá trueen mis pruebas. Sin embargo, si lanzamos -2147483648 a entero, el resultado será diferente:
if (int(-2147483648) > 0)
std::cout << "true";
else
std::cout << "false";
Esto se imprimirá false.
Estoy confundido. ¿Alguien puede dar una explicación sobre esto?
Actualización 02-05-2012:
Gracias por sus comentarios, en mi compilador, el tamaño de int es de 4 bytes. Estoy usando VC para algunas pruebas simples. He cambiado la descripción en mi pregunta.
Esas son muchas respuestas muy buenas en esta publicación, AndreyT dio una explicación muy detallada sobre cómo el compilador se comportará en dicha entrada y cómo se implementó este entero mínimo. qPCR4vir por otro lado dio algunas "curiosidades" relacionadas y cómo se representan los enteros. ¡Tan impresionante!
fuente

INT_MINde-9223372036854775808, siCHAR_BITes 16. E incluso conCHAR_BIT == 8ysizeof(int== 4) `puede obtener-9223372036854775807porque C no requiere números de 2 Complementos.Respuestas:
-2147483648No es un "número". El lenguaje C ++ no admite valores literales negativos.-2147483648es en realidad una expresión: un valor literal positivo2147483648con-operador unario en frente. El valor2147483648es aparentemente demasiado grande para el lado positivo delintrango en su plataforma. Si el tipolong inttuviera un rango mayor en su plataforma, el compilador tendría que asumir automáticamente que2147483648tienelong inttipo. (En C ++ 11, el compilador también tendría que considerar ellong long inttipo). Esto haría que el compilador evaluara-2147483648en el dominio de tipo más grande y el resultado sería negativo, como cabría esperar.Sin embargo, aparentemente en su caso el rango de
long intes el mismo que el rango deint, y en general no hay un tipo entero con un rango mayor queinten su plataforma. Esto significa formalmente que la constante positiva2147483648desborda todos los tipos de enteros con signo disponibles, lo que a su vez significa que el comportamiento de su programa no está definido. (Es un poco extraño que la especificación del lenguaje opte por un comportamiento indefinido en tales casos, en lugar de requerir un mensaje de diagnóstico, pero así es como es).En la práctica, teniendo en cuenta que el comportamiento es indefinido,
2147483648puede interpretarse como un valor negativo dependiente de la implementación que se vuelve positivo después de haberse-aplicado unario . Alternativamente, algunas implementaciones podrían decidir intentar usar tipos sin signo para representar el valor (por ejemplo, en C89 / 90 se requería usar compiladoresunsigned long int, pero no en C99 o C ++). Las implementaciones pueden hacer cualquier cosa, ya que el comportamiento no está definido de todos modos.Como nota al margen, esta es la razón por la cual las constantes como
INT_MINse suelen definir comoen lugar del aparentemente más directo
Este último no funcionaría según lo previsto.
fuente
#define INT_MIN (-2147483647 - 1).int. La implementación de OP puede no tener un tipo de 64 bits.-1.0se analice como un valor doble negativo, ¿no?unsigned long inten este contexto, pero en C99 este permiso fue eliminado. Se requieren literales sin sufijo en C y C ++ para tener tipos firmados . Si ve un tipo sin firmar aquí cuando uno con signo funcionaría, significa que su compilador está dañado. Si ve un tipo sin signo aquí cuando ningún tipo con signo funcionaría, entonces esto es solo una manifestación específica de comportamiento indefinido.El compilador (VC2012) promueve los enteros "mínimos" que pueden contener los valores. En el primer caso,
signed int(ylong int) no puede (antes de que se aplique el signo), perounsigned intpuede: ¿2147483648tieneunsigned int???? tipo. En el segundo forzasintdesde elunsigned.Aquí hay "curiosidades" relacionadas:
C ++ 11 estándar :
...
...
Y estas son las reglas de promociones para enteros en el estándar.
fuente
int,long int,unsigned long intpara representar las constantes decimales unsuffixed. Ese fue el único lenguaje que permitió el uso de tipos sin signo para constantes decimales sin mezclar. En C ++ 98 eraintolong int. No se permiten tipos sin firmar. Ni C (a partir de C99) ni C ++ permiten que el compilador use tipos sin signo en este contexto. Su compilador es, por supuesto, libre de usar tipos sin signo si ninguno de los firmados funciona, pero esto sigue siendo solo una manifestación específica de comportamiento indefinido.intolong intrepresentar2147483648. Además, que yo sepa, en tanto VC2012intylong intson tipos de 32 bits. Esto significa que en VC2012 literal2147483648debería conducir a un comportamiento indefinido . Cuando el comportamiento no está definido, el compilador puede hacer cualquier cosa. Eso significaría que VC2012 no está roto. Simplemente emitió un mensaje de diagnóstico engañoso. En lugar de decirle que el comportamiento es completamente indefinido, decidió usar un tipo sin signo.longy no está obligado a emitir un diagnóstico? Eso parecería roto.En resumen, se
2147483648desborda-2147483648y(-(-2147483648) > 0)estrue.Así es como se
2147483648ve en binario.Además, en el caso de los cálculos binarios con signo, el bit más significativo ("MSB") es el bit de signo. Esta pregunta puede ayudar a explicar por qué.
fuente
Debido a
-2147483648que en realidad se aplica2147483648con negación (-), el número no es lo que esperarías. En realidad es el equivalente de este pseudocódigo:operator -(2147483648)Ahora, suponiendo que su compilador sea
sizeof(int)igual4yCHAR_BITse defina como8, eso haría que el2147483648desbordamiento sea el valor máximo con signo de un entero (2147483647). Entonces, ¿cuál es el máximo más uno? Vamos a resolver eso con un entero de 4 bits y 2 segundos.¡Espere! 8 desborda el entero! qué hacemos? Utilice su representación sin signo
1000e interprete los bits como un entero con signo. Esta representación nos deja con la-8aplicación de la negación del complemento 2 que resulta en8, que, como todos sabemos, es mayor que0.Esta es la razón por la cual
<limits.h>(y<climits>) comúnmente se defineINT_MINcomo((-2147483647) - 1)- para que el entero con signo máximo (0x7FFFFFFF) se niegue (0x80000001), luego se disminuya (0x80000000).fuente
-8sigue siendo-8.-(8)qué en C ++ es lo mismo que-8: es la negación aplicada a un literal, no a un literal negativo. El literal es8, que no cabe en un entero de 4 bits con signo, por lo que debe estar sin signo. El patrón es1000. Hasta ahora tu respuesta es correcta. La negación del complemento de dos1000en 4 bits es1000que no importa si está firmado o no. Su respuesta dice "interprete los bits como un entero con signo", lo que hace que el valor-8después de la negación del complemento a los dos, tal como era antes de la negación.8. Se aplica la negación (módulo 16), dando como resultado una respuesta final de8. La codificación sigue siendo 1000 pero el valor es diferente porque se eligió un tipo sin signo.