元框架系列教程第一篇——快速启动NORP-Agent
2026/8/26 17:52:26
上节回顾:上一讲我们系统分析了C语言中异或运算的常见技巧与陷阱,包括变量交换、唯一元素查找、异或校验等典型应用,重点剖析了类型不一致、同地址操作、可读性、安全性等误区及其改进方法。
rand()函数生成的是伪随机数(Pseudo-Random Number),其本质是确定性算法,依赖一个“种子”值。srand(unsigned int seed)设置。未调用srand时,种子默认为1,导致每次运行产生相同的“随机”序列。rand()返回0 ~RAND_MAX(通常32767)之间的整数。rand() % N获得0~N-1的随机数,但这样会产生模偏差(Modulo Bias),即如果RAND_MAX+1不是N的整数倍,则部分取值概率会略高。time(NULL)作为种子初始化:srand((unsigned)time(NULL));,这样每次运行得到不同序列。srand(),否则会导致随机序列重置,降低随机性。rand()算法为线性同余法(LCG),周期短、分布不均,无法满足高强度安全需求。random(),arc4random(),mt19937等),或操作系统提供的真随机源(如/dev/urandom)。srand(),每次运行产生的“随机”序列都一样,丧失随机性,易被预测。srand()导致种子不断重置,序列短周期、严重影响分布和不可预测性。rand() % N,当RAND_MAX+1不是N的倍数时,某些结果出现概率略高。rand()非线程安全,多线程下可能出现序列交叉、重复。rand_r()为部分系统提供的线程安全版本,但不是C标准。RAND_MAX、rand()实现与行为在不同平台、编译器下可能有差异。main入口处初始化一次即可,勿在循环或其它函数重复调用srand()。arc4random、random、C++的<random>标准库,或专用密码学库。使用拒绝采样(rejection sampling)法,确保等概率分布:
intr,N=...;do{r=rand();}while(r>=RAND_MAX-(RAND_MAX%N));r=r%N;rand_r),或采用线程安全的生成器。#include<stdio.h>intmain(){printf("%d\n",rand());}问题:每次运行输出一样。
#include<stdio.h>#include<stdlib.h>#include<time.h>intmain(){srand((unsigned)time(NULL));printf("%d\n",rand());}for(inti=0;i<10;++i){srand(time(NULL));printf("%d\n",rand());}问题:循环很快,time(NULL)值基本不变,导致输出重复。
srand((unsigned)time(NULL));for(inti=0;i<10;++i){printf("%d\n",rand());}rand() % N引发模偏差intx=rand()%10;intN=10,r;do{r=rand();}while(r>=RAND_MAX-(RAND_MAX%N));intx=r%N;rand()的常见算法,周期短,分布不够理想。/dev/urandom),用于安全场合。rand() % N,通过拒绝采样消除模偏差。随机数管理看似简单,但一旦忽视种子初始化、分布均匀性和高并发等细节,极易引发隐蔽Bug和安全风险。工程实践中务必规范使用,确保代码健壮可靠。
公众号 | FunIO
微信搜一搜 “funio”,发现更多精彩内容。
个人博客 | blog.boringhex.top