c bit-shift unsigned

el desplazamiento de bits con tipo largo sin signo produce resultados incorrectos



bit-shift unsigned (4)

El 1 aquí, se llama una constante entera . Según las normas especificadas en el estándar, C11 , capítulo §6.4.4.1 la sintaxis para el mismo es

constante-entero:
sufijo de entero decimal constante sufijo opt
sufijo entero- octal-constante sufijo opt
sufijo entero- constante hexadecimal opt

y con respecto 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 que 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 << 63

Debería resolver su problema.

Tenga en cuenta: unsigned long se garantiza que el unsigned long sea ​​de 64 bits. unsigned long long garantiza tener al menos 64 bits . Sin embargo, siempre que esté utilizando la plataforma donde el unsigned long es de 64 bits, debería estar bien

Estoy un poco confundido porque quería inicializar una variable de tipo unsigned long cuyo tamaño es de 8 bytes en mi sistema (en todos los sistemas modernos, supongo). Sin embargo, cuando quiero asignar 1 << 63 a la variable, recibo una advertencia del compilador y el número es de hecho 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?


La expresión 1 << 63 tiene el 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. Intente (unsigned long)1 << 63 o 1UL << 63 para cambiar un valor de tipo unsigned long izquierda por 63 lugares.


Recomiendo que use 1ULL ya que esto le dará un entero sin signo de 64 bits en la arquitectura de 32 y 64 bits. En la arquitectura de 32 bits, la unsigned long (y, por lo tanto, UL ) tiene solo 32 bits y no resolverá el problema.

1ULL << 63


1 << 63 se calculará en aritmética int , y su int probablemente sea de 32 bits.

Remedie esto promoviendo uno de los argumentos: 1ULL << 63 lo hará.

ULL significa que la expresión será de al menos 64 bits.