如果rand()
函数创建一个长度为4个字节的随机数,并且我想创建一个长度为1024位(128字节)的随机数,那么最简单的方法就是通过连接来获得这个rand()
函数256次还是有替代方法?
#include <stdio.h>
#include <string.h>
int main(void) {
const char data[128];
memset(&data, 0x36, 128);
printf("%s\n", data);
puts("");
printf("%d\n", sizeof(data)/sizeof(data[0]));
puts("");
int i = 0;
unsigned long rez = 0;
for(i = 0; i < 20; i++) {
unsigned int num = rand();
rez = rez + num;
printf("%x\n", rez);
}
printf("%x\n", rez);
return 0;
}
答案 0 :(得分:3)
C标准规定RAND_MAX
的最小值为32767(0x7fff),因此最好在该假设下工作。
因为该函数只返回15个随机位,所以使用一次调用中的所有位将涉及一些位移和屏蔽以将结果放在适当的位置。最简单的方法是调用rand
128次,取每个结果的低位字节,然后将其写入字节数组:
unsigned char rand_val[128];
for (int i=0; i<128; i++) {
rand_val[i] = rand() & 0xff;
}
请不要忘记在代码之前的某处<{1}}完全一次。
如评论中提到的那样使用srand
将无效,因为此函数对空终止字符串起作用,而包含0的字节是有效随机数。
如果您打算将这些随机值用于涉及加密的任何内容,那么最好使用安全的随机数生成器。如果您有OpenSSL可用,请使用strcat
来实现此目的:
RAND_bytes
答案 1 :(得分:2)
在大多数POSIX(类Unix)系统上,您还可以从/dev/urandom
读取128个字节,您可以像二进制模式中的常规文件一样打开它 - 即使POSIX没有指定设备。
答案 2 :(得分:2)
是通过将rand()函数连接256次或是否有替代方法来获得此方法的最简单方法?
每个rand()
都会返回[0...RAND_MAX]
范围内的值。 RAND_MAX
仅限32767 <= RAND_MAX <= INT_MAX
。
非常常见RAND_MAX
是2 n 形式的Mersenne number - 1.代码可以利用这个非常常见的实现依赖值。然后,每个rand()
调用提供RAND_MAX_BITS
而不是32,如OP所建议的那样,提供4字节int
。 @Matteo Italia
#include <stdlib.h>
#if RAND_MAX == 0x7FFF
#define RAND_MAX_BITS 15
#elif RAND_MAX == 0x7FFFFFFF
#define RAND_MAX_BITS 31
#else
#error TBD code
#endif
致电rand()
⌈size * 8 / RAND_MAX_BITS⌉
次。这样可以减少rand()
所需的size
来电次数。
void rand_byte(uint8_t *dest, size_t size) {
int r_queue = 0;
int r_bit_count = 0;
for (size_t i = 0; i < size; i++) {
int r = 0;
//printf("%3zu %2d %8x\n", i, r_bit_count, r_queue);
if (r_bit_count < 8) {
int need = 8 - r_bit_count;
r = r_queue << need;
r_queue = rand();
r ^= r_queue; // OK to flip bits already saved in `r`
r_queue >>= need;
r_bit_count = RAND_MAX_BITS - need;
} else {
r = r_queue;
r_queue >>= 8;
r_bit_count -= 8;
}
dest[i] = r;
}
}
int main(void) {
uint8_t buf[128];
rand_byte(buf, sizeof buf);
...
return 0;
}
如果您想要最简单的代码,只需按@dbush
的答案为每个字节调用rand()
即可
答案 3 :(得分:0)
标准含糊地规定了C rand()
的属性;正如评论中所述,实际可用比特的数量取决于实现,并且它们的质量在历史上一直受到低于标准的实现的困扰。此外,rand()
影响程序的全局状态和,许多实现都不是线程安全的。
鉴于有一个好的,已知的和简单的PRNG,例如来自XorShift系列的PRNG,我只会使用其中一个。
#include <stdint.h>
/* The state must be seeded so that it is not all zero */
uint64_t s[2];
uint64_t xorshift128plus(void) {
uint64_t x = s[0];
uint64_t const y = s[1];
s[0] = y;
x ^= x << 23;
s[1] = x ^ y ^ (x >> 17) ^ (y >> 26);
return s[1] + y;
}
void next128bits(unsigned char ch[16]) {
uint64_t t = xorshift128plus();
memcpy(ch, &t, sizeof(t));
t = xorshift128plus();
memcpy(ch + 8, &t, sizeof(t));
}