Estoy un poco confundido porque quería inicializar una variable de tipo unsigned long cuyo tamaño es de 8 bytes en mi sistema (supongo que en todos los sistemas modernos). Sin embargo, cuando quiero asignar 1 << 63 a la variable, recibo una advertencia del compilador y, de hecho, el número es 0. Cuando hago 1 << 30 , obtengo el resultado esperado de 2 ^ 30 = 1073741824 . Sin embargo, cuando hago 1 << 31 , obtengo el resultado de 2 ^ 64 (creo; en realidad esto no debería ser posible) que imprime 18446744071562067968 .
¿Alguien puede explicarme este comportamiento?
1 << 63 se calculará en aritmética int , y su int probablemente sea de 32 bits.
Solucione esto promocionando uno de los argumentos: 1ULL << 63 lo hará.
ULL significa que la expresión tendrá al menos 64 bits.
La expresión 1 << 63 tiene tipo int . El rango de un int es -2 31 … 2 31 - 1 en la mayoría de los sistemas, 2 63 es demasiado grande para eso. Pruebe ya sea (unsigned long)1 << 63 o 1UL << 63 para desplazar un valor de tipo unsigned long 63 lugares a la izquierda.
El 1 aquí, se llama una constante entera . Por las normas especificadas en la norma, C11 , capítulo §6.4.4.1 la sintaxis del mismo es
constante entera:
decimal-constante entero-sufijo opt
octal-constante entero-sufijo opt
constante hexadecimal sufijo entero opt
y en cuanto a la Semántica,
El tipo de una constante entera es el primero de la lista correspondiente en la que se puede representar su valor.
y la tabla dice, si no hay sufijo, y el valor es representable en el rango int , debe considerarse como int . Entonces, 1 aquí, se considera un int , que generalmente es de 4 bytes, o 32 bits, también lo mismo en su caso.
Para especificar explícitamente el 1 como bit unsigned long (64), podemos usar el sufijo, como
1UL << 63debería resolver su problema.
Tenga en cuenta: no se garantiza que unsigned long sea de 64 bits. Se garantiza que unsigned long long tiene al menos 64 bits . Sin embargo, siempre que esté utilizando la plataforma donde el unsigned long es de 64 bits, debería estar bien