Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 从内联字节重新组装浮点_C_Embedded_Type Punning - Fatal编程技术网

C 从内联字节重新组装浮点

C 从内联字节重新组装浮点,c,embedded,type-punning,C,Embedded,Type Punning,我正在与HiTech PICC32合作开发PIC32MX系列微处理器,但我认为这个问题对于任何熟悉C语言的人来说都足够普遍。(这几乎相当于C90,sizeof(int)=sizeof(long)=sizeof(float)=4。) 假设我读取了一个4字节的数据字,它表示一个浮点值。我可以通过以下方法将其快速转换为实际浮点值: #define FLOAT_FROM_WORD(WORD_VALUE) (*((float*) &(WORD_VALUE))) 但这只适用于左值。例如,我不能在函

我正在与HiTech PICC32合作开发PIC32MX系列微处理器,但我认为这个问题对于任何熟悉C语言的人来说都足够普遍。(这几乎相当于C90,sizeof(int)=sizeof(long)=sizeof(float)=4。)

假设我读取了一个4字节的数据字,它表示一个
浮点值
。我可以通过以下方法将其快速转换为实际浮点值:

#define FLOAT_FROM_WORD(WORD_VALUE) (*((float*) &(WORD_VALUE)))
但这只适用于左值。例如,我不能在函数返回值上使用此选项,例如:

FLOAT_FROM_WORD(eeprom_read_word(addr));
是否有一种简单的内联方式来实现这一点,即不需要函数调用或临时变量?老实说,我没有太多的理由避免函数调用或额外的var,但这让我感到困扰。我一定错过了一条路


补充道:我不知道
WORD
实际上是一种常见的typedef。我已经更改了宏参数的名称以避免混淆。

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

float fl;
*(int*)&fl = eeprom_read_word(addr);

或者正如塞缪尔·克拉奇科所暗示的那样

#define  ASTYPE(type, val) (*(type*)&(val))
ASTYPE(WORD,fl) = eeprom_read_word(addr);

不是一个真正的答案,更多的是一个建议。您的FLOAT_FROM_WORD宏将更自然地使用,如果没有;最后

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

fl = FLOAT_FROM_WORD(wd);

在您的具体情况下,这可能是不可能的,但升级到C99编译器也会解决您的问题


C99具有内联函数,虽然在参数和返回值方面与普通函数类似,但在这种情况下,它可以提高效率,而不存在宏的任何缺点。

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

FLOAT_FROM_WORD(w) (*(float*)&(const WORD &)(w))
但这在c语言中是行不通的:(

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


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

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

#define atob(original, newtype) \
  (((union { typeof(original) i; newtype j })(original)).k)
哇。很可怕。但是用法很好:

int i = 0xdeadbeef;
float f = atob(i, float);
我敢打赌,您的编译器既不支持GCC所支持的
typeof
运算符,也不支持
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
casting,这是一种简洁但不可移植的技巧,那么就没有办法按照“您想要的方式”来执行,其他答案已经得到了。

“但这只适用于右值”你是说左值?不管怎样,通过优化,你的编译器无论如何都应该删除函数调用;只需将其粘贴到函数中,然后查看程序集就可以找到。更正[l/r]值的东西。稍后将查看汇编。我建议您将这种东西放在特定于平台的包装函数中,以使此特定于平台的代码仅限于项目的一小部分。这都是特定于平台的-此代码是专门为PIC32MX[3/4]编写的60F512L.HiTech不做C99编译器,所以…不行:/n如果您想进一步推广,您可以创建将变量视为宏参数的类型
#定义ASTYPE(var,type)(*(type*)和(var))
,然后像
ASTYPE(fl,WORD)一样使用它=…
很好的建议,我会把它添加到回答中快速简单,我喜欢。干杯。确保eeprom的读/写例程的结尾正确:)可悲的是,Microchip实际上是一个基于GCC的编译器,他们已经从技术上发布了源代码。然而,我从来没有能够诱使它在Linux上编译。
#define atob(original, origtype newtype) \
  (((union { origtype i; newtype j })(original)).k)

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