Я вижу поведение, которого не ожидаю при компиляции этого кода с разными уровнями оптимизации в gcc.
Функциональный тест должен заполнить 64-разрядное целое число без знака единицами, сдвинуть их биты shift_size влево и вернуть 32 младших бита в виде 32-разрядного целого числа без знака.
Когда я компилирую с -O0, я получаю ожидаемые результаты.
Когда я компилирую с -O2, я не делаю, если я пытаюсь сместиться на 32 или более бит.
Фактически, я получаю именно те результаты, которые ожидаю, если бы я сдвигал 32-битное целое число на сдвиги, большие или равные ширине бит на x86, что является сдвигом, использующим только 5 младших битов размера сдвига.
Но я сдвигаю 64-битное число, поэтому сдвиги <64 должны быть законными, верно? </p>
Я предполагаю, что это ошибка в моем понимании, а не в компиляторе, но я не смог ее выяснить.
Моя машина:
gcc (Ubuntu / Linaro 4.4.4-14ubuntu5) 4.4.5
i686-Linux-гну
#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;
}
Использование:
$ gcc -Wall -O0 test.c
$ ./a.out 32
0l
$ gcc -Wall -O2 test.c
$ ./a.out 32
4294967295l
gcc -S -Wall -O0 test.c
gcc -S -Wall -O2 test.c