5

我在 PIC32MX 系列微处理器上使用 HiTech PICC32,但我认为这个问题对于任何熟悉 C 语言的人来说已经足够普遍了。(这几乎等同于 C90,sizeof(int) = sizeof(long) = sizeof(float ) = 4.)

假设我读取了一个 4 字节的数据字,它代表float. 我可以使用以下方法快速将其转换为实际的浮点值:

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

但这仅适用于左值。例如,我不能在函数返回值上使用它,例如:

FLOAT_FROM_WORD(eeprom_read_word(addr));

是否有一种简短而甜蜜的方式来内联,即没有函数调用或临时变量?老实说,我没有理由避免函数调用或额外的 var,但这让我很烦恼。一定有我想念的方法。

补充:我没有意识到这WORD实际上是一个常见的 typedef。我更改了宏参数的名称以避免混淆。

4

5 回答 5

9

您可以以另一种方式运行该技巧以获取返回值

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);
于 2010-02-10T06:01:55.977 回答
3

如果这是 GCC,你可以这样做:

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

哇。可怕。但是用法很好:

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

我敢打赌,您的编译器既不支持typeof运算符也不支持unionGCC 所做的转换,因为这两者都不是标准行为,但是如果您的编译器无法进行union转换,那就是您的答案。修改为不使用typeof

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

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

当然,这忽略了当你使用两种不同尺寸时会发生什么的问题,但更接近“你想要的”,即返回一个值的简单宏过滤器,而不是采用额外的参数。此版本采用的额外参数仅用于通用性。

如果您的编译器不支持union强制转换,这是一个简洁但不可移植的技巧,那么就无法按照“您想要的方式”执行此操作,并且其他答案已经得到了它。

于 2010-02-10T07:58:50.363 回答
1

如果使用 const 引用,则可以获取临时值的地址:

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

但这在c中不起作用:(

(c 没有引用对吗?在 Visual c++ 中工作)

正如其他人所说,无论是内联函数还是定义中的临时,编译器都会对其进行优化。

于 2010-02-10T07:15:26.767 回答
0

不是真正的答案,更多的是建议。如果您的 FLOAT_FROM_WORD 宏没有 ; 在末尾

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

fl = FLOAT_FROM_WORD(wd);
于 2010-02-10T06:13:22.440 回答
0

在您的确切情况下可能不可能,但升级到 C99 编译器也可以解决您的问题。

C99 具有内联函数,虽然在参数和返回值中的作用类似于普通函数,但在这种情况下提高了效率,而没有宏的缺点。

于 2010-02-10T06:28:45.313 回答