Получение битов одиночной точности IEEE для поплавка

Мне нужно написать число с плавающей точкой с одинарной точностью IEEE в 32-разрядный аппаратный регистр по конкретному адресу. Для этого мне нужно преобразовать переменную типа float в целое число без знака. Я могу получить целочисленное представление следующим образом:

float a = 2.39;
unsigned int *target;
printf("a = %f\n",a);
target = &a;
printf("target = %08X\n",*target);

который возвращает:

a = 2.390000
target = 4018F5C3

Все хорошо. Однако это вызывает предупреждение компилятора "cast.c: 12: warning: назначение из несовместимого типа указателя"

Есть ли другой способ сделать это, не генерируя предупреждение? Это относится к конкретному оборудованию, мне не нужно обрабатывать разные контенты и т.д., И я не хочу прокручивать каждый char по соображениям производительности, как это обычно указывают некоторые другие вопросы. Похоже, что вы можете использовать reinterpret_cast в С++, но я использую C.

Ответ 1

Вы можете использовать тип punning с объединением,

union {
    float f;
    uint32_t u;
} un;
un.f = your_float;
uint32_t target = un.u;

чтобы получить бит. Или вы можете использовать memcpy.

Ответ 2

Вы можете создать тип union, содержащий float и unsigned int, сохранить значение в члене float, а затем прочитать его из int, например:

union reg_val
{
  float f_val;
  unsigned int i_val;
} myRegister;
myRegister.f_val = 2.39;
printf("target = %08X", myRegister.i_val);

Ответ 3

Если вы пытаетесь просто отобразить интегральное значение float по мере его хранения в памяти, попробуйте использовать union:

union {
    float a;
    unsigned int target;
} u;

Сохранить значение поплавка:

u.a = 2.39;

Распечатайте как значения float, так и целочисленные значения:

printf ("a = %f\n", u.a);
printf ("target = %08X\n", u.target); /* you could use %u to show decimal */

Нет предупреждений компилятора. Я использую GNU-компилятор (gcc) для Linux. Обратите внимание, что target не является указателем; это красота (и отвратительность) профсоюзов.; -)

Ответ 4

EDIT: профсоюзное решение работает везде, где я его пробовал, но где-то там, я был указан в стандартах, которые показали, что он не должен работать. См. Ссылку ниже в комментариях, чтобы найти LOT дополнительную информацию об этом (Спасибо, Даниэль!). Предположим, что я работаю или не должен работать, я буду использовать его с осторожностью, я думаю, что и энтузиазм и т.д. (Удваивается, разбивается на байты и т.д.).

Другое решение - это функция-заглушка asm. Например, на руке:

.globl echo 
echo:
   bx lr


unsigned int echo ( float );
...
unsigned int ra; float f;
f=1.0;
ra=echo(f);

требуется некоторая разборка, должна быть в системе, которая не имеет fpu и/или использует gprs для переноса плавающих элементов.

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