type - bit fields c
Asignando entero de 128 bits en C (2)
¿Estoy haciendo algo mal o es un error en gcc?
El problema está en la parte 47942806932686753431
, no en __uint128_t p
. De acuerdo con los documentos de gcc, no hay forma de declarar una constante de 128 bits:
No hay soporte en GCC para expresar una constante entera de tipo __int128 para objetivos con un entero largo largo de menos de 128 bits.
Por lo tanto, parece que si bien puede tener variables de 128 bits, no puede tener constantes de 128 bits, a menos que su long long
sea de 128 bits de ancho.
La solución podría ser construir un valor de 128 bits a partir de constantes integrales "más estrechas" utilizando operaciones aritméticas básicas, y esperar que el compilador realice el plegado constante .
Cuando intento asignar un entero de 128 bits en gcc 4.9.1, warning: integer constant is too large for its type
una warning: integer constant is too large for its type
.
Código de ejemplo
int main(void) {
__uint128_t p = 47942806932686753431;
return 0;
}
Salida
Estoy compilando con gcc -std=c11 -o test test.c
y obtengo:
test.c: In function ‘main’:
test.c:2:19: warning: integer constant is too large for its type
__uint128_t p = 47942806932686753431;
^
¿Estoy haciendo algo mal o es un error en gcc?
¿Has probado esto?
__int128 p = *(__int128*) "/x00/x01/x02/x03/x04/x05/x06/x07/x08/x09/x0a/x0b/x0c/x0d/x0e/x0f";
EDITAR 25 de noviembre
Perdón por la mala aclaración en el post anterior. En serio, no publiqué esta respuesta como una broma. Aunque el documento de GCC indica que no hay manera de expresar una constante entera de 128 bits, esta publicación simplemente proporciona una solución para aquellos que desean asignar valores a las variables __uint128_t con facilidad.
Puede intentar complicar el código siguiente con GCC (7.2.0) o Clang (5.0.0). Imprime los resultados deseados.
#include <stdint.h>
#include <stdio.h>
int main()
{
__uint128_t p = *(__int128*) "/x00/x01/x02/x03/x04/x05/x06/x07/x08/x09/x0a/x0b/x0c/x0d/x0e/x0f";
printf("HIGH %016llx/n", (uint64_t) (p >> 64));
printf("LOW %016llx/n", (uint64_t) p);
return 0;
}
El stdout:
HIGH 0f0e0d0c0b0a0908
LOW 0706050403020100
Esto solo se considera como una solución alternativa, ya que reproduce los trucos de los punteros al colocar el "valor" en la sección .rodata (si lo objdump) y no es portátil (x86_64 y aarch64 están bien, pero no arman y x86). Creo que ha sido suficiente para aquellos que codifican en máquinas de escritorio.