我应该使用哪个 *_cast 将任意整数类型指针转换为 char 指针?
Posted
技术标签:
【中文标题】我应该使用哪个 *_cast 将任意整数类型指针转换为 char 指针?【英文标题】:Which *_cast should I use to cast an arbitrary integer-type pointer to a char pointer? 【发布时间】:2014-03-11 02:49:05 【问题描述】:我需要用 /dev/urandom 中的数据填充一个整数类型变量(任意大小)。考虑到这一点,我有以下代码:
std::fstream fstr("/dev/urandom", std::fstream::in | std::fstream::binary);
fstr.read(reinterpret_cast<char*>(&randomseed), sizeof(randomseed));
fstr.close();
(randomseed 是我需要用随机数据填充的变量)。
这会做正确的事(即无论库实现如何,它都是安全的),还是我应该使用其他一些 *_cast?
【问题讨论】:
你选对了演员,这是reinterpret_cast
,但不要忘记错误处理,阅读后检查流对象的错误标志。
@pasztorpisti 当然,为了简洁起见,我只是不想在代码 sn-p 中包含它。谢谢!
@Veeno 不错,不客气。
【参考方案1】:
这不安全。只有char
类型保证没有陷阱表示。
“正确”的解决方案是将 /dev/urandom
包装在 C++ <random>
引擎中,并使用 std::uniform_int_distribution
。
【讨论】:
我究竟如何将/dev/random
包装在<random>
引擎中?我的意思是,我知道我在这里做的是“hacky”,但<random>
引擎实现本身在某些时候是否必须有类似的“hack”?更安全的解决方案是不使用istream::read
而是使用istream::get
来一次从/dev/random
中获取一个字节?
@Veeno:现有引擎不受大多数 UB 规则的约束,因为它们被视为实现的一部分,并且可能依赖于实现的其他部分。也就是说,您当然可以一次读取 4 个字节并将它们放入 unsigned long
- 只需将第二个字节移动 8 位,将第三个字节移动 16 位,将第四个字节移动 24 位。由于操作是数字的并且在类型的范围内,因此您没有陷阱问题。当然,这可能会使一些位为零,但这对于随机引擎来说不是问题。分布会使用随机引擎的最小值/最大值来处理这个问题。
嗯...为什么我一次可以从/dev/urandom
中读取四个字节,但不能读取一个? :( 读取一个char
不意味着只读取一个字节吗?我可以读取四个字节sizeof(randomseed)
次,将每个四个字节按位异或到一个字节,相应地移位并用随机数据填充变量randomseed
,但这似乎非常浪费——我宁愿只从/dev/urandom
中读取我需要的数据。
呃,恐怕你真的没听懂。你可以读一个,只是不是很随机(只有 256 种可能性)。此外,您似乎非常坚持sizeof(randomseed)
,但这是一个毫无意义的数字。不会告诉您允许的值范围。为此,您有std::numeric_limits
,然后您可以使用它来选择合适的std::uniform_int_distribution
。
好吧,我被“困”在sizeof(randomseed)
上,因为这告诉我需要从/dev/urandom
中读出多少字节才能用随机数据填充整个randomseed
... 是的,一个字节只有 256 种可能性,我知道,但是如果我读取四个字节,那仍然是 256^4 = 2^32 种可能性,无论我是一次读取一个还是一次读取全部四个。以上是关于我应该使用哪个 *_cast 将任意整数类型指针转换为 char 指针?的主要内容,如果未能解决你的问题,请参考以下文章
使用static_cast进行父类指针转子类指针可能出现的问题
reinterpret_cast and const_cast
[C/C++]_[中级]_[static_cast的详细解析]