Estoy tratando de establecer el bit más significativo en un largo, largo, sin firmar, x. Para hacer eso estoy usando esta línea de código:
x |= 1<<((sizeof(x)*8)-1);Pensé que esto debería funcionar, porque sizeof da el tamaño en bytes, así que multipliqué por 8 y resté uno para establecer el bit final. Cada vez que hago eso, el compilador tiene esta advertencia: "advertencia: recuento de desplazamiento a la izquierda> = ancho de tipo"
No entiendo por qué se produce este error.
El 1 que está cambiando es una constante de tipo int , lo que significa que está cambiando un valor int por tamaño de sizeof(unsigned long long) * 8) - 1 bits. Este cambio puede ser fácilmente más que el ancho de int , que aparentemente es lo que sucedió en su caso.
Si desea obtener una máscara de bits de tipo unsigned long long , debe comenzar con una máscara de bits inicial de tipo unsigned long long , no de tipo int .
1ull << (sizeof(x) * CHAR_BIT) - 1Podría decirse que una mejor manera de construir la misma máscara sería
~(-1ull >> 1)o
~(~0ull >> 1)use 1ULL << en lugar de 1 <<
Usar solo "1" te hace cambiar un número entero. 1ULL será un largo sin firmar, que es lo que necesita. Un número entero será probablemente de 32 bits long long probablemente de 64 bits de ancho. Entonces cambiando:
1 << ((sizeof(long long)*8)-1)será (muy probablemente):
1 << 63Dado que 1 es un número entero que es (muy probablemente) 32 bits, recibe una advertencia porque está tratando de pasar el MSB de un valor de 32 bits.
El literal 1 que está cambiando no es automáticamente un unsigned long long (sino un int ) y, por lo tanto, no tiene tantos bits como necesita. Agregue el sufijo ULL (es decir, 1ULL ), o conviértalo en unsigned long long antes de cambiarlo para que sea del tipo correcto.
Además, para ser un poco más seguro para plataformas extrañas, reemplace 8 con CHAR_BIT . Tenga en cuenta que esta no es necesariamente la mejor manera de establecer el bit más significativo; consulte, por ejemplo, esta pregunta para conocer las alternativas.
También debe considerar el uso de un tipo como uint64_t si supone que unsigned long long tiene un cierto ancho, o uint_fast64_t / uint_least64_t si necesita al menos un cierto ancho, o uintmax_t si necesita el tipo más grande disponible.