转换为联合和奇怪的数字格式

时间:2012-02-17 09:58:39

标签: c++ c

有人能告诉我如何让这个C代码在C ++中工作吗?

uint64_t flv_dbl2int( double value )
{
    return (union {double f; uint64_t i;}){value}.i;    
}

我不确定发生了什么,是否有点转变?

4 个答案:

答案 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;    
}