【问题标题】:Reassemble float from bytes inline从字节内联重新组装浮点数
【发布时间】:2010-02-10 05:52:04
【问题描述】:

我在 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));

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

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

【问题讨论】:

  • "但这仅适用于右值" 你是说左值吗?无论如何,通过优化,您的编译器无论如何都应该删除函数调用;只需将其粘贴在一个函数中,然后查看程序集即可。
  • 更正了 [l/r] 值的东西。稍后会看组装。
  • 我建议你把这种东西放在一个特定于平台的包装函数中,以将这个特定于平台的代码限制在你项目的一小部分。
  • 都是平台特定的——这段代码是专门为 PIC32MX[3/4]60F512L 编写的。

标签: c embedded type-punning


【解决方案1】:

您可以通过其他方式运行该技巧以获取返回值

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);

【讨论】:

  • 如果你想进一步概括,你可以让类型将变量视为宏参数#define ASTYPE(var, type) (*(type*)&(var)),然后像ASTYPE(fl, WORD) = ...一样使用它
  • 好建议,我会添加到答案中
  • 快速简单,我喜欢。干杯。
  • 确保字节序与您的 eeprom 读/写例程正常工作:)
【解决方案2】:

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

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

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

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

我敢打赌,你的编译器既不支持typeof 运算符,也不支持 GCC 支持的 union 转换,因为这两者都不是标准行为,但是你的编译器可能会进行 union 转换,那是你的答案。修改为不使用typeof

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

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

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

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

【讨论】:

  • 可悲的是,Microchip 实际上制作了一个基于 GCC 的编译器,而且他们已经在技术上发布了源代码。但是,我一直无法哄它在 Linux 上编译。
【解决方案3】:

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

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

但这在 c 中不起作用:(

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

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

【讨论】:

    【解决方案4】:

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

    #define FLOAT_FROM_WORD(w) (*(float*)&(w))
    
    fl = FLOAT_FROM_WORD(wd);
    

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

      • HiTech 不制作 C99 编译器,所以...没有办法:/
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-21
      • 2014-02-22
      相关资源
      最近更新 更多