Estoy viendo un comportamiento que no espero al compilar este código con diferentes niveles de optimización en gcc.Niveles de optimización en gcc cambiando el comportamiento del programa c
La prueba de función debe llenar un entero sin signo de 64 bits con unos, desplazar los bits de desplazamiento a la izquierda y devolver los 32 bits bajos como un entero sin signo de 32 bits.
Cuando compilo con -O0 obtengo los resultados que espero.
Cuando compilo con -O2 no lo hago, si intento cambiar 32 bits o más.
De hecho, obtengo exactamente los resultados que esperaría si estuviera cambiando un entero de 32 bits por cambios mayores o iguales que el ancho de bits en x86, que es un cambio usando solo los 5 bits bajos del tamaño de desplazamiento .
Pero estoy cambiando un número de 64 bits, por lo que los cambios < 64 deberían ser legales ¿no?
Supongo que es un error en mi comprensión y no en el compilador, pero no he podido descifrarlo.
Mi máquina: gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 i686-linux-gnu
#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>
uint32_t test(unsigned int shift_size) {
uint64_t res = 0;
res = ~res;
res = res << shift_size; //Shift size < uint64_t width so this should work
return res; //Implicit cast to uint32_t
}
int main(int argc, char *argv[])
{
int dst;
sscanf(argv[1], "%d", &dst); //Get arg from outside so optimizer doesn't eat everything
printf("%" PRIu32 "l\n", test(dst));
return 0;
}
Uso:
$ gcc -Wall -O0 test.c
$ ./a.out 32
0l
$ gcc -Wall -O2 test.c
$ ./a.out 32
4294967295l
¿Podría también publicar las partes relevantes del código ensamblador generado por su compilador? ('-S' para gcc) –
FWIW da el resultado correcto (' 0l') para mí en todos los niveles de optimización de '-O0' a' -O3' usando gcc 4.2.1, así que sospecho que * might * have encontró un error de gcc. –
hm, el código funciona bien en ambos niveles de optimización para mí ... (gcc versión 4.5.0 20100604, openSUSE 11.3 (x86_64)) – Bort