在线重新组合浮点数

时间:2010-02-10 05:52:04

标签: c embedded type-punning

我正在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。我已经更改了宏参数的名称以避免混淆。

5 个答案:

答案 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具有内联函数,虽然它们在参数和返回值中起到正常函数的作用,但在这种情况下可以提高效率,而且没有宏的缺点。