Если вы хотите использовать тип punning, вам понадобится элемент float
в объединении.
Кроме того, доступ к битам определяется реализацией компилятора. Первый бит в struct
не обязательно MSB. Это может быть младший бит или любой бит посередине ...
Это верно, даже если мы примем реализацию IEEE 754 с плавающей запятой . Переключение компиляторов может нарушить схему доступа к битам.
Кроме того, case
не может сравнивать строки, AFAIK ... Идея case "NaN"
не сработает.
Выфактически сравнивая адрес строки в argv[1]
с адресом скомпилированной строки ("NaN") в сегменте data
скомпилированного файла - эти адреса никогда не будут совпадать с .
В качестве последнего примечания atof
возвращает double
, а не число с плавающей запятой. C89 описывает strtod
, C99 добавляет strtof
... strtof
- это, вероятно, нужная вам функция, она возвращает float
.
В качестве дополнительного бонуса, strtof
охватывает NaN
и Inf
во многих вариациях. Это позволит вам позже проверить NaN.
Учитывая эти проблемы, ваша функция может выглядеть так (не проверено):
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
struct my_bitfield_t {
int b1 : 2;
int b2 : 6;
};
union my_union_t {
struct my_bitfield_t b;
uint8_t i;
uint32_t u;
float f;
};
int main(int argc, char **argv) {
if (argc != 2)
goto error;
union my_union_t u;
u.f = strtof(argv[1], 0);
if (isnan(u.f) || isinf(u.f)) {
/* there are many possible NaN values, they can't fit in `switch` */
/* the same is true for infinity (positive / negative) */
printf("%f\n", u.f);
} else {
printf("%d\n", u.b.b2); /* implementation specific bit ordering */
printf("%d\n", (u.u >> 22) & 1023);
/* print bit by bit */
for (size_t i = 0; i < 32; ++i) {
uint8_t bit = (u.u >> (31 - i)) & 1;
printf("%d", bit);
if (i == 0 || i == 8)
printf("|");
}
printf("\n");
}
return 0;
error:
printf("Input a single floating point number\n");
return -1;
}