c++ 64bit bit-shift

En C++, ¿cuál es la diferencia entre 1 y 1i64?



64bit bit-shift (4)

1i64 Creo que debería ser un entero de 64 bits con signo. No puedo procurar ninguna experiencia en la implementación de Microsoft, pero en GCC, la solución para admitir enteros de 64 bits en las CPU de 32 bits consistía en hacer palabras largas de doble longitud usando estructuras y varias macros de magia negra. Por lo tanto, i64 debe ser compatible.

En cuanto al último bit de vudú, el único punto al especificar 1u es porque es posible que si k sea lo suficientemente grande, el resultado del cambio alcanzaría / superaría los 32 bits de almacenamiento, en cuyo caso el resultado será diferente si el operando LH se trata como un entero con signo o sin signo.

Estoy convirtiendo un código compatible de 32 bits a 64 bits, y he encontrado un obstáculo. Estoy compilando un proyecto VS2008 x64, y recibo esta advertencia:

warning C4334: ''<<'' : result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)

Aquí está la línea de código original:

if ((j & (1 << k)) != 0) {

Y esto es lo que parece si sigo los consejos de Microsoft :

if ((j & (1i64 << k)) != 0) {

¿Es seguro hacerlo, cuando el código se compilará en sistemas de 32 y 64 bits? Si es así, explique por qué debo agregar "i64" al final y por qué esto no afectará a una compilación de 32 bits. De lo contrario, una solución sería muy apreciada.

Más allá de esto, tengo lo que parece un código aún más complicado.

if (id[j] != id[j ^ (1u << k)]) {

Entiendo que la "u" significa que el dígito no está firmado, pero ¿qué sentido tiene especificar que en un valor que no exceda el valor máximo firmado ... Supongo que esto tiene algo que ver con el cambio de bits?


Dado que ese código es ''y'' de la variable de 64 bits j con el resultado (de 32 bits) de un desplazamiento de bits, el compilador ''expandirá'' el resultado a 64 bits.

Es probable que desee controlar la forma en que se calcula el segundo operando de ''y'', por lo que el compilador le sugiere que use los 64 bits completos al hacer que el primer operando sea __int64 . Esto es seguro en 32 bits, pero en realidad debería mirar el tipo de j para decidir si el operador tiene 32 o 64 bits.

Eso es especialmente importante en el segundo bit, donde el resultado se utiliza como un índice.


El sufijo i64 es específico de Microsoft. Para ser más portátil (si está preocupado por eso), puede usar la macro INT64_C() de stdint.h :

#include <stdint.h> // ... if ((j & (INT64_C( 1) << k)) != 0) { ... }

Desafortunadamente, MS no tiene stdint.h como parte de su biblioteca C (la mayoría de los otros compiladores parecen tenerlo), pero afortunadamente puedes obtener uno de varias fuentes:

Ahora tendrás una constante de 64 bits que funcionará con una amplia variedad de compiladores.

En cuanto a por qué puede querer o necesitar el valor de 64 bits, depende de los tipos de las distintas partes de la expresión. Sería útil saber los tipos de id , j y k para poder responder si necesita el sufijo '' u '' en la constante o no, y qué efecto podría tener.


1 tiene el tipo int según C ++ Standard. En el compilador de Microsoft de 64 bits int tiene sizeof = 4 bytes, esto significa que int es una variable de 32 bits. 1i64 tiene tipo __int64 .

Cuando utiliza el operador de cambio, el tipo de resultado es el mismo que el tipo del operando izquierdo. Significa que al cambiar 1 obtendrás un resultado de 32 bits. El compilador de Microsoft supone que podría no ser lo que está esperando (en una plataforma de 64 bits) y le da un mensaje de advertencia.

Cuando uses 1i64 resultado será de 64 bits en ambas plataformas. j y 0 se convertirán implícitamente a 64 bits. Entonces, toda la expresión se calculará en variables de 64 bits y el resultado será bool .

Así que usar 1i64 es seguro en ambas plataformas (32/64).