Приведение ((DWORD) 0xFFFFFFFF) к одинарной точности с плавающей запятой без изменения двоичного значения

Я хочу скомпилировать одинарную точность с плавающей запятой во флэш-память как 0xFFFFFFFF (неинициализированная флэш-память).

Когда я пытаюсь использовать (FLOAT32) ((UINT32) 0xFFFFFFFF), в процессе компиляции он преобразуется в число с плавающей запятой (0x0000804F) вместо 0xFFFFFFFF.

Это относится к инициализации поля в структуре в файловой области. Когда я думаю об этом, это означает, что компилятор ожидает литерал FLOAT32.

Я начинаю задаваться вопросом, возможно ли это на самом деле.

[EDIT: это относится к инициализации поля в структуре в области файла]


person Christian Madsen    schedule 13.12.2013    source источник


Ответы (4)


В C лучше всего использовать union. Сохраните в поле UINT32, затем прочитайте его из поля float.

Полное обсуждение здесь: Как преобразовать или преобразовать число с плавающей запятой в его битовую последовательность, такую ​​как long

Кроме того, если у вас есть доступные функции C99, вы можете использовать назначенные инициализаторы, чтобы указать, какое из полей объединения вы хотите назначить. Даже если у вас нет C99, вы можете просто убедиться, что поля UINT32 в union являются первыми, поэтому они будут назначены по умолчанию. http://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html

person steveha    schedule 13.12.2013
comment
Спасибо. Отличное предложение и ссылка. К сожалению, это работает только в области блока, а не в области файла (которую мне нужно использовать). - person Christian Madsen; 13.12.2013
comment
@ChristianMadsen, который меняет дело. Я добавил ответ для этого. - person Bernd Elkemann; 13.12.2013
comment
ChristianMadsen, почему вы думаете, что это не работает в области файлов? @eznme привел пример кода, показывающий, как именно это использовать для статической инициализации в области файла. - person steveha; 13.12.2013
comment
И @bkausbk привел два примера, один из которых показывает обозначенную функцию инициализатора C99, а другой показывает простой C. - person steveha; 13.12.2013

Как вы просите в комментарии: здесь, в неблочной области (вы можете сделать глобальную или файловую область):

#include <inttypes.h>
#include <stdio.h>
typedef union {
    uint32_t uint32;
    float f;
} aliasing;
aliasing a = { 0xffffffff };
int main(){
    printf("%u %f\n", a.uint32, a.f); // output: 4294967295 -1.#QNAN0
    return 0;
}

Кроме того, если вы хотите, чтобы это было внутри структуры (ваш исходный вопрос) и все еще хотите статическую инициализацию, вы можете сделать:

#include <inttypes.h>
#include <stdio.h>
typedef union {
    uint32_t uint32;
    float f;
} aliasing;
typedef struct {
    aliasing a;
    int otherstuff;
} thestruct_t;
thestruct_t thestruct = { { 0xffffffff }, 0 };
int main(){
    printf("%u %f\n", thestruct.a.uint32, thestruct.a.f); 
         // output: 4294967295 -1.#QNAN0
    return 0;
}
person Bernd Elkemann    schedule 13.12.2013
comment
Я думаю, вы хотите printf("%" PRIu32 " %f\n", a.uint32, a.f) для sizeof(unsigned) может быть 2. - person chux - Reinstate Monica; 13.12.2013
comment
Я должен упомянуть, что я не могу изменить определение типа структуры. Мне разрешено только изменять значение поля. Например: typedef struct { float myfloat; } thestruct_t;thestruct_t thestruct = { { 0xffffffff }, 0 }; - person Christian Madsen; 16.12.2013

Я думаю, что использование союзов, а затем приведение к нему любого типа будет работать:

typedef union _DATA {
    UINT32 AsInteger;
    FLOAT AsFloat;
} DATA;

char* Buffer = malloc(...);
ReadFromFile(Buffer, 1000);

// Casting
// ((DATA*) (Buffer + Offset))->AsFloat
// ((DATA*) (Buffer + Offset))->AsInteger

Или статически

DATA MyData;
MyData.AsInteger = 0xffffffff;

// C99
DATA MyData = {.AsInteger = 0xffffffff};

// C
DATA MyData = {0xffffffff};
person bkausbk    schedule 13.12.2013
comment
Не используйте идентификаторы, начинающиеся со знака подчеркивания, например _DATA; слишком легко вторгнуться в пространство имен реализации и вызвать неопределенное поведение. Особенно, когда с большой буквы. - person Jens; 13.12.2013

Одним из решений может быть использование абсолютного размещения. Это может или не может быть возможно с вашими инструментами.

Примечание. Я никогда этого не делал, и синтаксис здесь, вероятно, даже не подходит для любого компилятора. Это только пример намерения.

UINT32 const i = 0xFFFFFFFF @ 0x12345678; /* Place i at address 0x12345678 */
extern FLASH32 const f @ 0x12345678;  /* Pretend that f is at the same address */
person user694733    schedule 13.12.2013