Saltar al contenido

¿Por qué el int más pequeño, −2147483648, tiene el tipo ‘long’?

Solución:

C ª, -2147483648 no es una constante entera. 2147483648 es una constante entera, y - es solo un operador unario que se le aplica, lo que produce una expresión constante. El valor de 2147483648 no encaja en un int (es demasiado grande, 2147483647 es típicamente el número entero más grande) y, por lo tanto, la constante entera tiene el tipo long, que causa el problema que observa. Si desea mencionar el límite inferior de un int, usa la macro INT_MIN de <limits.h> (el enfoque portátil) o evite cuidadosamente mencionar 2147483648:

printf("PRINTF(d) t: %dn", -1 - 2147483647);

El problema es ese -2147483648 no es un literal entero. Es una expresión que consta del operador de negación unario. - y el entero 2147483648, que es demasiado grande para ser un int si ints son 32 bits. Dado que el compilador elegirá un entero con signo de tamaño apropiado para representar 2147483648 antes de aplicar el operador de negación, el tipo de resultado será mayor que un int.

Si sabes que tu ints son de 32 bits y desea evitar la advertencia sin mutilar la legibilidad, use una conversión explícita:

printf("PRINTF(d) t: %dn", (int)(-2147483648));

Ese es el comportamiento definido en una máquina en complemento a 2 con 32 bits ints.

Para una mayor portabilidad teórica, utilice INT_MIN en lugar del número, y háganos saber dónde encontró una máquina que no sea complemento a 2 para probarla.


Para ser claros, ese último párrafo fue en parte una broma. INT_MIN es definitivamente el camino a seguir si te refieres a “el más pequeño int“, porque int varía en tamaño. Todavía hay muchas implementaciones de 16 bits, por ejemplo. Escribiendo -231 solo es útil si definitivamente siempre te refieres exactamente a ese valor, en cuyo caso probablemente usarías un tipo de tamaño fijo como int32_t en lugar de int.

Es posible que desee alguna alternativa a escribir el número en decimal para que sea más claro para aquellos que no noten la diferencia entre 2147483648 y 2174483648, Pero tienes que tener cuidado.

Como se mencionó anteriormente, en una máquina de complemento a 2 de 32 bits, (int)(-2147483648) no se desbordará y, por lo tanto, está bien definido, porque -2147483648 se tratará como un tipo firmado más amplio. Sin embargo, no ocurre lo mismo con (int)(-0x80000000). 0x80000000 será tratado como un unsigned int (ya que encaja en la representación sin firmar); -0x80000000 está bien definido (pero el - no tiene efecto si int es de 32 bits), y la conversión de la resultante unsigned int 0x80000000 para int implica un desbordamiento. Para evitar el desbordamiento, necesitaría convertir la constante hexadecimal a un tipo firmado: (int)(-(long long)(0x80000000)).

Del mismo modo, debe tener cuidado si desea utilizar el operador de cambio a la izquierda. 1<<31 es un comportamiento indefinido en máquinas de 32 bits con 32 bits (o menos) ints; solo evaluará a 231 si int es de al menos 33 bits, porque el desplazamiento a la izquierda por k bits solo está bien definido si k es estrictamente menor que el número de bits sin signo del tipo entero del argumento de la izquierda.

1LL<<31 es seguro, ya que long long int se requiere poder representar 263-1, por lo que su tamaño de bits debe ser mayor que 32. Por lo tanto, el formulario

(int)(-(1LL<<31))

es posiblemente el más legible. YMMV.


Para cualquier pedante que apruebe, esta pregunta está etiquetada como C, y el último borrador de C (n1570.pdf) dice, con respecto a E1 << E2, dónde E1 tiene un tipo firmado, que el valor se define solo si E1 es no negativo y E1 × 2E2 “se puede representar en el tipo de resultado”. (§6.5.7 párrafo 4).

Eso es diferente de C ++, en el que la aplicación del operador de desplazamiento a la izquierda se define si E1 es no negativo y E1 × 2E2 “es representable
en el tipo sin firmar correspondiente del tipo de resultado “(§5.8 párr. 2, énfasis añadido).

En C ++, de acuerdo con el borrador de estándar más reciente, la conversión de un valor entero a un tipo entero con signo es definido por la implementación si el valor no se puede representar en el tipo de destino (§4.7 párr. 3). El párrafo correspondiente de la norma C – §6.3.1.3 párr. 3 – dice que “o el resultado está definido por la implementación o se genera una señal definida por la implementación”.)

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : / /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *