Повторно соберите плавание от встроенных байтов

Я работаю с HiTech PICC32 на серии PIC32MX микропроцессоров, но я думаю, что этот вопрос является достаточно общим для любого хорошо осведомленного в C. (Это почти эквивалентно C90 с sizeof (интервал) = sizeof (долго) = sizeof (плавание) = 4.)

Скажем, я считал 4-байтовое слово данных, которые представляют a float. Я могу быстро преобразовать его в его фактическое значение плавающее с:

#define FLOAT_FROM_WORD(WORD_VALUE) (*((float*) &(WORD_VALUE)))

Но это только работает на lvalues. Я не могу, например, использовать это на функциональном возвращаемом значении как:

FLOAT_FROM_WORD(eeprom_read_word(addr));

Существует ли короткий и сладкий способ сделать, это встраивает, т.е. без вызова функции или временной переменной? Честно говоря, нет никакой ОГРОМНОЙ причины для меня избежать вызова функции или дополнительного var, но он прослушивает меня. Должен быть способ, которым я отсутствую.

Добавленный: Я не понял это WORD было на самом деле общее определение типа. Я изменил имя макро-аргумента для предотвращения беспорядка.

5
задан detly 10 February 2010 в 06:54
поделиться

5 ответов

Вы можете проделать этот трюк в другую сторону для возвращаемых значений

float fl;
*(int*)&fl = eeprom_read_word(addr);

или

#define WORD_TO_FLOAT(f)  (*(int*)&(f))

WORD_TO_FLOAT(fl) = eeprom_read_word(addr);

или, как предлагает R Samuel Klatchko

#define  ASTYPE(type, val) (*(type*)&(val))
ASTYPE(WORD,fl) = eeprom_read_word(addr);
8
ответ дан 13 December 2019 в 05:34
поделиться

Каталог проекта можно копировать и вставлять в другую папку без каких-либо проблем.

-121--2953979-

Просто сделайте копию папки, в которой находится ваш проект, а затем используйте файл проекта из вашей копии. вы также можете сделать снимок, если вы просто ищете резервную копию, прежде чем попробовать некоторые идеи кода.

-121--2953976-

можно выбрать адрес временного значения, если используется ссылка const:

FLOAT_FROM_WORD(w) (*(float*)&(const WORD &)(w))

, но она не будет работать в c: (

(c не имеет ссылок? работает в визуальном c++)

, как говорили другие, будь то встроенная функция или временная в определении, компилятор оптимизирует ее.

1
ответ дан 13 December 2019 в 05:34
поделиться

Не совсем ответ, скорее предложение. Ваш макрос FLOAT_FROM_WORD будет более естественным и гибким, если он не имеет; в конце

#define FLOAT_FROM_WORD(w) (*(float*)&(w))

fl = FLOAT_FROM_WORD(wd);
0
ответ дан 13 December 2019 в 05:34
поделиться

Если бы это был GCC, вы могли бы сделать вот что:

#define atob(original, newtype) \
  (((union { typeof(original) i; newtype j })(original)).k)

Вау. Ужасно. Но использование хорошее:

int i = 0xdeadbeef;
float f = atob(i, float);

Держу пари, что ваш компилятор не поддерживает ни оператор typeof, ни приведение union, которое делает GCC, поскольку ни то, ни другое не является стандартным поведением, но если вдруг ваш компилятор может делать приведение union, то это ваш ответ. Модифицировано, чтобы не использовать typeof:

#define atob(original, origtype newtype) \
  (((union { origtype i; newtype j })(original)).k)

int i = 0xdeadbeef;
float f = atob(i, int, float);

Конечно, это игнорирует вопрос о том, что происходит, когда вы используете два типа разных размеров, но это ближе к "тому, что вы хотите", т.е. простой макрофильтр, который возвращает значение, а не принимает дополнительный параметр. Дополнительные параметры в этой версии берутся только для общности.

Если ваш компилятор не поддерживает union кастинг, который является аккуратным, но непортируемым приемом, то нет способа сделать это "так, как вы хотите", и другие ответы уже получили это.

3
ответ дан 13 December 2019 в 05:34
поделиться

Возможно, в вашей ситуации это невозможно, но обновление до компилятора C99 решило бы и вашу проблему.

В C99 есть встроенные функции, которые, действуя как обычные функции в параметрах и возвращаемых значениях, получают улучшенную эффективность именно в этом случае без недостатков макросов.

0
ответ дан 13 December 2019 в 05:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: