Преобразование шестнадцатеричного числа в плавающее - PullRequest
0 голосов
/ 14 июля 2020

Я разбираю заголовок в файле. В файле есть значение с плавающей запятой, которое я хочу извлечь. В комментариях указано, что это значение типа float32, но я не уверен, как его извлечь.

Учитывая такой буфер, как мне его правильно извлечь? Обратите внимание, что это прямой порядок байтов.

unsigned char b[4];
b[0] = 0xa1;
b[1] = 0xb2;
b[2] = 0xc3;
b[3] = 0xd4;

float f = b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24;
printf("f is %f\n", f);

Чтобы быть более ясным: проблема в том, что независимо от того, какое значение в файле (буфере), десятичное число всегда .000000. Как мне узнать, где должна находиться эта десятичная дробь go?

Ответы [ 2 ]

3 голосов
/ 14 июля 2020

Безопасный способ:

unsigned char b[sizeof(float)];
float f;
memcpy(&f, b, sizeof(f));

очень вероятно, что хороший компилятор оптимизирует вызов memcpy, и этот метод будет очень эффективным.

g cc безопасный способ

union {
  unsigned char b[sizeof(float)];
  float f;
}a = {.b = {0xa1, 0xb2, 0xc3, 0xc4}};

printf("%f" , a.f); 

или каламбур, как в ответе @AnttiHaapala

2 голосов
/ 14 июля 2020

Если целевая архитектура имеет float32 в качестве представления и имеет тот же порядок байтов, что и исходный, то это так же просто, как:

float f;
unsigned char *b = (unsigned char *)&f;

b[0] = 0xa1;
b[1] = 0xb2;
b[2] = 0xc3;
b[3] = 0xd4;

printf("f is %f\n", f);

Если источник данных и ваша целевая архитектура имеют малый / большой порядок байтов несоответствие, просто поменяйте индексы на 3 ... 0. Если у вас есть другая странная устаревшая последовательность байтов, мне вас жаль.

Обратите внимание, что вы можете использовать memcpy - для чего вам нужно будет использовать вспомогательный буфер, а не просто то, что выполняет итерацию байтов; или объединение, которое будет содержать больше кода и не обязательно совместимо с C ++.

...