从4字节char数组到int的精度损失?

时间:2016-07-16 13:39:29

标签: c++ fstream

我试图从/ dev / random中提取一个整数值的数据。以下代码有效。我试图理解的是为什么我必须使用size_t类型作为最终输出以避免精度损失。请参阅代码中的注释。

我认为问题可能是.read方法添加了某种类型的填充,例如空终止字符,我尝试将长度设置为3以避免这种情况,但它似乎并不重要。我很高兴知道如何解决这个问题,但我想明白为什么我必须这样做。

size_t getSeed()
{
    std::ifstream rnd ("/dev/random", std::ios::binary);
    if( rnd.is_open() )
    {
        int len = sizeof(int);               // 4 bytes
        char* blk = new char [len];
        rnd.read ( blk, len );               // 8 bytes?
        rnd.close();
        size_t out = (size_t)*blk;           // loss of precision with int
        delete[] blk;
        return out;
    }
    else
    {
        return 0;
    }
}  

1 个答案:

答案 0 :(得分:1)

我无法理解您为何以二进制模式阅读4 char,然后将其保存到int,即size_t。从流直接读到size_t out会更容易:

 size_t out;
 rnd.read ( &out, sizeof(out) );

但是,如果它只是一个实验,我想提出一些变体来将4个char打包成一个32位int。

union有第一个(C风格)选项:

#include <cstdint>

union ConversionUnion
{
    int32_t dint;
    char dchar[4];
}; 

int32_t getSeed()
{
    std::ifstream rnds ("/dev/random", std::ios::binary);
    ConversionUnion conv;
    if( rnds.is_open() )
    {
        rnds.read (conv.dchar, sizeof(int32_t ));
        rnds.close();
        return conv.dint;
    }
    else
    {
        return 0;
    }
} 

如果您只想修改代码,请尝试更改行

size_t out = (size_t)*blk; 

到行(这也是C而不是C ++)

size_t out = *((size_t*)blk);

还要考虑针对4个数字(不是数组)的解决方案 - here。但是相同的方法可以用于数组:

    int32_t result = 0;
    for(int i = 0; i < 4; i++) // or
    // for(int i = 3; i > 0; i--)  // for reverse order of bytes if needed
    {
        result <<= 8;
        result |= blk[i];
    }