我试图从/ 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;
}
}
答案 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];
}