0

如何intVariable = *(int*) &floatVariable直接从函数中获得效果,而不必先将函数的输出保存到虚拟变量中?

IE

float functionWithFloatTypedReturn(int input) {
    [enter code here]
    return serialStringStruct.floatRetVal;
}
...
intVariable = [desired code] functionWithFloatTypedReturn(commandCode);

背景:我有一个从别人的硬件给出的串行响应中读取的函数。遗留代码和对语言能力的好奇心促使人们继续使用单一功能。如果函数返回数值“1”,它可以是 0x3f800000 或 0x1,具体取决于函数的输入(它决定了向硬件提供的命令)。来自硬件的串行字符串通过调用 memcpy 独立于类型分解为结构。

4

3 回答 3

3
intVariable = (union { float f; int i; }) { functionWithFloatTypedReturn(commandCode) } .i;

这使用包含联合的复合文字来重新解释值的字节(在 C 1999 及更高版本中受支持)。

请注意,通常建议使用无符号整数而不是int访问浮点编码的位,因为无符号整数不太容易出现某些问题,例如位移的符号问题。

您还必须确保您使用的两种类型在您的 C 实现中具有相同的字节数。

此代码在没有中间 C 变量的情况下完成了重新解释。但是,这并不意味着它在机器语言实现中会更有效。

于 2013-11-25T23:31:55.067 回答
2

您不能,部分原因是许多编译器在浮点寄存器(或 FPU 堆栈)中返回浮点值,因此必须先将它们存储到“常规”内存中,然后才能以按位方式访问它们。

您可以使用内联函数进行转换。请注意,标准 C 并未定义将浮点位模式视为整数位模式(反之亦然)的效果,但可以取决于您的实现,因为您必须这样做。只需将其放入某种“取决于实现”文件(头文件、模块等)中即可。

(我建议寻找一种方法对其进行重构,以隐藏其余代码中的硬件可变性。)

于 2013-11-25T23:21:41.280 回答
0

如果您有支持 C99 标准的编译器,则可以使用复合文字:

intVariable = *(int *)&(float){ functionWithFloatTypedReturn(commandCode) };

正如 Eric Postpischil 在评论中指出的那样, aunion没有与指针类型双关语相同的别名问题:

intVariable = (union { float f; int i; }){ .f = functionWithFloatTypedReturn(commandCode) }.i;

然而,这提出了一种更好的方法 -floatRetVal将 struct 的成员更改为union包含 afloat和 an 的a int,并直接union从函数返回该类型:

union retval {
    float f;
    int i;
};

union retval functionWithUnionTypedReturn(int input) {
    [enter code here]
    return serialStringStruct.floatOrIntRetVal;
}

然后知道它将获得float返回类型的代码使用:

floatVariable = functionWithUnionTypedReturn(commandCode).f;

并且知道它将获得int返回类型的代码使用:

intVariable = functionWithUnionTypedReturn(commandCode).i;
于 2013-11-25T23:31:14.030 回答