用随机数据填充内存区域

Populate a region of memory with random data

我正在尝试使用 rand 跨平台以一种有效的方式随机填充数据区域。这是我目前所拥有的:

/**********************************************\
*          Useful macro by Glen Ragen          *
*  *
\**********************************************/
#if 1 /* So that the IDE minifies it */
#define NEEDS_BIT(N, B)     (((unsigned long)N >> B) > 0)

#define BITS_TO_REPRESENT(N)                   \
        (NEEDS_BIT(N,  0) + NEEDS_BIT(N,  1) + \
         NEEDS_BIT(N,  2) + NEEDS_BIT(N,  3) + \
                         ...
         NEEDS_BIT(N, 60) + NEEDS_BIT(N, 61) + \
         NEEDS_BIT(N, 62) + NEEDS_BIT(N, 63)   \
        )
#endif /* So that the IDE minifies it */

typedef struct {
    size_t size; /* Size in bytes */
    void *pointer;
} data;

void fill_data_with_randomness(const data data) {
    for (size_t biti = 0; biti < data.size * 8; biti += BITS_TO_REPRESENT(RAND_MAX)) {
        /* Fill data.pointer with bits from rand() */
    }
}

由于 RAND_MAX 是一个编译时常量,所以 BITS_TO_REPRESENT(RAND_MAX) 也应该是。由于 data 属于 const data 类型,因此 data.size * 8 应该能够优化为调用时间常量,而不是在 for 循环的每次迭代中都进行评估。

但是,位操作很慢,fill_data_with_randomness函数会被调用的很频繁。此函数应在具有 2^n-1 形式的任何 RAND_MAX 值的系统上正确编译 运行。什么 fill_data_with_randomness 函数可以快速地用 rand()mness 填充这个内存区域而不浪费位?

RAND_MAX 保证至少为 215−1 因此通过一次调用 [=11= 随机填充整个字节是没有问题的],除非你的架构有大于 15 位的字节(在这种情况下,你的硬编码乘以 8 也会有问题)。

逐字节进行生成非常简单,不需要位黑客技巧。

就我个人而言,我不会担心 "wasting bits" 来自对 rand() 的调用;该标准库函数生成的位在大多数实现中价值不大。真正的问题是决定丢弃哪些位,以便剩余的位合理分布。如果可能的话,为了应对通常使用的劣质 PRNG 的范围,您应该选择中间位。

更好的解决方案可能是简单地提供您自己的 PRNG;存在可移植的源代码实现,其中一些已得到很好的研究。