Переменные с плавающей точкой, в соответствии с IEEE 754, представляют собой составные структуры данных с тремя или четырьмя компонентами: знак, экспонента, мантисса и, необязательно, тихий флаг NaN (встроенный в мантиссу).Сдвиг представления всей памяти, как вы сделали в fi_union.val = *(uint64_t*)(&v1) >> i;
, не вернет ничего значимого.
Таким образом, ожидаемые результаты действительно те, которые вы видите на первой итерации, когда i = 0,сдвиг не выполняется и возвращенное значение в порядке.Когда вы начинаете сдвигать биты в представлении памяти с плавающей запятой, вы устанавливаете бит знака над экспонентой, биты экспоненты над мантиссой и т. Д. Это вызывает беспорядок.
Если вы хотите проверить содержимоепредставления памяти числа с плавающей запятой, используйте <ieee754.h>
из glibc.
Примерно так (не проверено):
#include <ieee754.h>
...
union ieee754_double x;
x.d = v1
printf("sign: %u; mantissa: %llu; exponent: %u\n",
(unsigned) x.ieee.negative,
((unsigned long long) x.ieee.mantissa1 << 20) | ((unsigned long long) x.ieee.mantissa0),
(unsigned) x.ieee.exponent - IEEE754_DOUBLE_BIAS);