有人能告诉我如何让这个C代码在C ++中工作吗?
uint64_t flv_dbl2int( double value )
{
return (union {double f; uint64_t i;}){value}.i;
}
我不确定发生了什么,是否有点转变?
答案 0 :(得分:5)
据我所知,C ++中打字类型的唯一法律策略是memcpy()
,即
uint64_t flv_dbl2int(double fvalue)
{
uint64_t ivalue;
memcpy(&ivalue, &fvalue, sizeof ivalue);
return ivalue;
}
使用reinterpret_cast
uint64_t flv_dbl2int(double value)
{
return reinterpret_cast<uint64_t&>(value);
}
实际上是未定义的行为,与使用C风格的指针强制转换相同。
使用联合(作为原始解决方案),虽然在C中是合法的,但在C ++中可能非法。在实践中,所有这些解决方案都可能有效,至少gcc-4.5.3和clang-3.0将在-O1
的x86上生成相同的代码。
答案 1 :(得分:3)
这使用复合文字将double
值解释为uint64_t
。此构造在C ++中不可用。只需在return语句之前创建union类型的临时变量,并使用该变量的i
字段进行返回。
uint64_t flv_dbl2int( double value )
{
union {double f; uint64_t i;} tmp = { value };
return tmp.i;
}
编辑:如果在评论中有人声称这是C ++中的“非法”,那么最好的办法就是将其声明为extern "C"
并将其编译为C(而不是C ++)在一个单独的编译单元中。你也应该知道,在任何情况下这都是一个邪恶的黑客,double
不能保证是64位宽。如果您(或您继承的代码)只对浮点值的各个部分感兴趣,请使用适当的函数frexp
。
答案 2 :(得分:0)
此C99代码正在初始化具有double
值的匿名联合,然后返回占用相同内存的uint64_t
值。这是一种获取&#34;位的方法。代表double
,但不推荐使用。
事实上,读取不同的联盟成员而不是上次写入的成员是不明确的行为。
更好的方法可能就是使用指针魔术:
uint64_t flv_dbl2int( double value )
{
return *((uint64_t *) &value);
}
答案 3 :(得分:0)
在投射时使用指针
请记住:“类型可能无法在演员阵容中定义”
uint64_t flv_dbl2int( double value )
{
union Foo {double f; uint64_t i;};
return (*(Foo *)&value).i;
}