Доступ к битам данных с плавающей точкой - Невозможно найти решение - PullRequest
0 голосов
/ 08 ноября 2019

Так что я застрял в том, что мне нужно написать, чтобы программа распечатала правильный вывод. Это означает, что когда я набираю число «0,15625», оно теоретически должно распечатать «0 | 01111100 | 01000000000000000000000»

Но я просто не понимаю, как или какое решение мне нужнополучить ожидаемый результат.

Помощь будет оценена

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>

struct my_bitfield_t{
  int b1 : 2;
  int b2: 6;
};

union my_union_t{
  struct my_bitfield_t b;
  uint8_t i;
};

int main(int argc, char ** argv){
  float Not_A_NUmber = NAN;
  float No_infinity = INFINITY;
  switch(argv[1]){
    case "" : printf("Input a number\n");
      break;
    case "NaN": printf("%f\n", Not_A_NUmber);
      break;
    case "Infinity": printf("%f\n", No_infinity);
      break;
    default: float value = atof(argv[1]);
      union my_union_t u;
      u.i = (int) value;
      //print individual bits
      printf("%d\n", u.b.b2);
  }
  return 0;
}

1 Ответ

0 голосов
/ 08 ноября 2019

Если вы хотите использовать тип 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;
}
...