traduccion - type casting c++
¿Qué es "int i=1; ¿Por qué(i>=60*60*1000/1*1000)" verdadero? (9)
Primero, la definición de dos expresiones constantes sin paréntesis es mi culpa:
#define BIG_INTERVAL 60 * 60 * 1000
#define SMALL_INTERVAL 1 * 1000
int i = 1;
if (i >= BIG_INTERVAL / SMALL_INTERVAL - 1)
{
printf("Oops!/n");
}
La instrucción if
después de la expansión de macro es if(i >= 60 * 60 * 1000 / 1 * 1000 - 1)
.
Esa no es mi intención. Pero encuentro algo extraño si escribo if (i >= 3600000000 - 1)
. Es falso.
¿Qué tipo es 60 * 60 * 1000 / 1 * 1000 - 1
? int
?
60 * 60 * 1000/1 * 1000 - 1 = 3600000 * 1000 - 1, que desborda el tipo int, por lo que el resultado puede ser cualquier cosa (en su caso es negativo, pero no tiene que ser así).
Para lograr lo que quiere poner ():
#define BIG_INTERVAL (60 * 60 * 1000)
#define SMALL_INTERVAL (1 * 1000)
Algo que no he visto a nadie mencionar es que incluso paréntesis completas de las definiciones de macro no resuelve completamente el problema.
La pregunta tiene:
#define BIG_INTERVAL 60 * 60 * 1000
(y el interrogador reconoce que la falta de paréntesis es un problema). Pero incluso con:
#define BIG_INTERVAL (60 * 60 * 1000)
cada una de las constantes (60, 60 y 1000) es definitivamente representable como int, pero el producto es 3600000, mientras que el lenguaje solo garantiza que INT_MAX >= 32767
.
El lenguaje dice que las constantes de enteros grandes son de un tipo lo suficientemente grande como para contener sus valores (por ejemplo, 100000
puede ser de tipo int
o de tipo long int
, dependiendo de los rangos de esos tipos), pero no tiene dicha regla para expresiones, incluso expresiones constantes.
Puedes solucionar esto de esta manera:
#define BIG_INTERVAL (60L * 60L * 1000L)
pero eso hace que sea de tipo long
aunque no sea necesario.
En cuanto al problema de precedencia del operador, este es mi ejemplo favorito:
#include <stdio.h>
#define SIX 1+5
#define NINE 8+1
int main(void)
{
printf("%d * %d = %d/n", SIX, NINE, SIX * NINE);
return 0;
}
La salida, por supuesto, es
6 * 9 = 42
(ver Douglas Adams).
Aquí están mis resultados de prueba:
60 * 60 * 1000 / 1 * 1000 will result to -694967296
(60 * 60 * 1000) / (1*1000) will result to 3600
Hay un problema con su operación, la precedencia de los cálculos.
Es posible que desee considerar consultar la precedencia de operador C ++ http://msdn.microsoft.com/en-us/library/126fe14k%28v=vs.80%29.aspx . Encontrarás la razón por la cual el resultado se convirtió en -694967296, lo que creo que es un efecto de desbordamiento.
Cada uno de los argumentos para esa expresión es un número entero, por lo que el resultado será un número entero.
Creo que estás confundido acerca de cómo funcionan las macros. No está utilizando los valores de esas macros, sino las ecuaciones mismas. Creo que esta es tu confusión. Creo que deberías hacer paréntesis en tus macros o no usar macros.
Lo más probable es que salgas del rango válido de valores para un int. Firmado: ¡3600000000 es un número bastante grande!
Cuando esto sucede, el valor se convertirá en el valor negativo más pequeño para el tipo de datos int.
Esto dará como resultado que su declaración sea verdadera.
Podría ser que estás desbordando el tamaño de un int que está 2147m más o menos firmado, lo que significa que si pasas la representación para eso se convierte en negativo. Como se señala en otras respuestas, la división no hace nada cuando se expande, de modo que rodea las definiciones de macro con paréntesis
Si usa un compilador donde int es de 64 bits, encontrará que el resultado de su expresión es falso. Si usa un compilador en el que int es de 32 bits o 16 bits, su expresión tiene un comportamiento indefinido porque el desbordamiento de las notas firmadas no tiene que envolverse. Probablemente el tuyo simplemente se envolvió, pero no tiene por qué ser así.
3600000000 es una constante visible en tiempo de compilación, por lo que si int es solo 32 bits, entonces tu compilador deberá elegir long long (o simplemente long si long es 64 bits). Entonces su otra expresión se evalúa con suficientes bits para evitar el desbordamiento, y el resultado es correcto.
Todos los operadores en int
s return int
. Entonces sí, 60 * 60 * 1000 / 1 * 1000 - 1
es un int
. Pero el resultado esperado de 3599999999 es demasiado grande para una int
, por lo que la expresión en realidad se evalúa como -694967297 (suponiendo el complemento de 32 bits y el complemento de dos).
Esto no sucede con un literal de 3600000000
porque los literales enteros más grandes que INT_MAX
son de un tipo que puede contener el valor completo.