Я работаю с 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
было на самом деле общее определение типа. Я изменил имя макро-аргумента для предотвращения беспорядка.
Вы можете проделать этот трюк в другую сторону для возвращаемых значений
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);
Каталог проекта можно копировать и вставлять в другую папку без каких-либо проблем.
-121--2953979-Просто сделайте копию папки, в которой находится ваш проект, а затем используйте файл проекта из вашей копии. вы также можете сделать снимок, если вы просто ищете резервную копию, прежде чем попробовать некоторые идеи кода.
-121--2953976-можно выбрать адрес временного значения, если используется ссылка const:
FLOAT_FROM_WORD(w) (*(float*)&(const WORD &)(w))
, но она не будет работать в c: (
(c не имеет ссылок? работает в визуальном c++)
, как говорили другие, будь то встроенная функция или временная в определении, компилятор оптимизирует ее.
Не совсем ответ, скорее предложение. Ваш макрос FLOAT_FROM_WORD будет более естественным и гибким, если он не имеет; в конце
#define FLOAT_FROM_WORD(w) (*(float*)&(w))
fl = FLOAT_FROM_WORD(wd);
Если бы это был 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
кастинг, который является аккуратным, но непортируемым приемом, то нет способа сделать это "так, как вы хотите", и другие ответы уже получили это.
Возможно, в вашей ситуации это невозможно, но обновление до компилятора C99 решило бы и вашу проблему.
В C99 есть встроенные функции, которые, действуя как обычные функции в параметрах и возвращаемых значениях, получают улучшенную эффективность именно в этом случае без недостатков макросов.