出于测试和学习的目的,我想修改https://github.com/php/php-src中的php rand 和 mt_rand 函数:ext / standard / rand.c。
我想在每次调用rand函数时给出一个固定的输出,为此我修改了代码
PHPAPI long php_rand(TSRMLS_D)
{
long ret;
if (!BG(rand_is_seeded)) {
php_srand(GENERATE_SEED() TSRMLS_CC);
}
#ifdef ZTS
ret = php_rand_r(&BG(rand_seed));
#else
# if defined(HAVE_RANDOM)
ret = random();
# elif defined(HAVE_LRAND48)
ret = lrand48();
# else
ret = rand();
# endif
#endif
// ignoring the results coming from the calls above and
// returning a constant value
ret = 3264;
return ret;
}
编译
./configure
make
make install
最后将rand函数称为echo rand(3000,4000);
,它始终返回3000
。
修改此功能的方法是什么?为什么有TSRMLS_D
而不是范围参数?
答案 0 :(得分:2)
从PHP调用的实际函数是声明为PHP_FUNCTION(rand)
的函数,它调用您修改的php_rand()
函数。它执行以下操作:
PHP_FUNCTION(rand)
{
long min;
long max;
long number;
int argc = ZEND_NUM_ARGS();
if (argc != 0 && zend_parse_parameters(argc TSRMLS_CC, "ll", &min, &max) == FAILURE)
return;
number = php_rand(TSRMLS_C);
if (argc == 2) {
RAND_RANGE(number, min, max, PHP_RAND_MAX);
}
RETURN_LONG(number);
}
如您所见,如果您传入2个参数,则会调用RAND_RANGE
宏,这会将php_rand()
的结果转换为给定的范围。
#define RAND_RANGE(__n, __min, __max, __tmax) \
(__n) = (__min) + (long) ((double) ( (double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))
如果您希望始终输出给定值,我建议您修改PHP_FUNCTION(rand)
,而不是php_rand()
。
虽然如果您正在寻找的是稳定的随机数输出,那么您每次都会获得相同的结果,如果您不关心确切的结果,您可以在开始时调用srand(0)
您的程序,使用常量值为随机数生成器播种。这意味着随机数生成器将始终为您提供相同的随机数序列,这对于测试目的非常有用,并且可以在不修补PHP本身的情况下完成。
答案 1 :(得分:0)
查看php_rand.h中的RAND_RANGE宏定义。它对输入值进行一些额外的置换/加扰,使其适合您指定的范围。
如果你真的希望rand()函数返回3264,即使它不适合传递给rand()的参数,在rand.c中删除这个块:
if (argc == 2) {
RAND_RANGE(number, min, max, PHP_RAND_MAX);
}
如果您仍想考虑最小值/最大值,如果您指定的最小值/最大值不包括您的硬编码,您将需要弄清楚您想要实际执行的操作。