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.