我正在PIC32MX系列微处理器上使用HiTech PICC32,但我认为这个问题对于C中的任何人来说都是足够普遍的(这几乎相当于C90,sizeof(int)= sizeof(long)= sizeof(float)= 4。)
假设我读了一个代表float
的4字节数据字。我可以使用以下命令快速将其转换为实际的浮点值:
#define FLOAT_FROM_WORD(WORD_VALUE) (*((float*) &(WORD_VALUE)))
但这仅适用于左值。例如,我不能在函数返回值上使用它,如:
FLOAT_FROM_WORD(eeprom_read_word(addr));
有没有简短而甜蜜的方式来内联,即没有函数调用或临时变量?说实话,我没有任何理由避免函数调用或额外变量,但它让我烦恼。必须有一种我不知道的方式。
已添加:我没有意识到WORD
实际上是一个常见的typedef。我已经更改了宏参数的名称以避免混淆。
答案 0 :(得分:8)
您可以以其他方式运行技巧以获取返回值
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);
答案 1 :(得分:3)
如果这是GCC,你可以这样做:
#define atob(original, newtype) \
(((union { typeof(original) i; newtype j })(original)).k)
哇。可怕。但用法很好:
int i = 0xdeadbeef;
float f = atob(i, float);
我敢打赌你的编译器既不支持typeof
运算符也不支持GCC执行的union
转换,因为它们都不是标准行为,但是你的编译器可能会执行{{{ 1}}施法,这是你的答案。修改为不使用union
:
typeof
当然,这忽略了当您使用两种不同大小时会发生什么的问题,但更接近“您想要的”,即一个返回值的简单宏过滤器,而不是采用额外的参数。此版本采用的额外参数仅用于通用性。
如果你的编译器不支持#define atob(original, origtype newtype) \
(((union { origtype i; newtype j })(original)).k)
int i = 0xdeadbeef;
float f = atob(i, int, float);
转换,这是一个整洁但非便携的技巧,那么就没有办法以“你想要的方式”做到这一点,而其他答案已经得到了它
答案 2 :(得分:1)
如果使用const引用,则可以获取临时值的地址:
FLOAT_FROM_WORD(w) (*(float*)&(const WORD &)(w))
但这不适用于c :(
(c没有引用权?在visual c ++中有效)
正如其他人所说,无论是内联函数还是定义中的temp,编译器都会优化它。
答案 3 :(得分:0)
不是一个真正的答案,更多的建议。您的FLOAT_FROM_WORD宏使用起来会更自然,如果没有,则更灵活;最后
#define FLOAT_FROM_WORD(w) (*(float*)&(w))
fl = FLOAT_FROM_WORD(wd);
答案 4 :(得分:0)
在您的确切情况下可能无法实现,但升级到C99编译器也可以解决您的问题。
C99具有内联函数,虽然它们在参数和返回值中起到正常函数的作用,但在这种情况下可以提高效率,而且没有宏的缺点。