2012-11-19 50 views
3

为了测试和学习的目的,我想修改PHP 兰特mt_rand功能,这些功能在https://github.com/php/php-src:EXT /标准/ rand.c。修改PHP rand函数

我想给一个固定的输出每次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但不是范围参数?

+1

这是一个c问题不是php的问题。 – 2012-11-19 18:47:16

+0

@Dagon我错过了,感谢您的纠正! – amertkara

回答

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本身的情况下完成。

+0

非常感谢!我修改了PHP_FUNCTION(rand),它工作。我将使用该函数而不是php_rand。 – amertkara

+0

其实,修改的主要原因不是给出固定输出,我想测试rand和mt_rand上的一些东西。固定输出只是为了理解事情的工作方式。 – amertkara

+1

@acidrous足够的公平,我想这可能是这种情况,但想确保我包含有关'srand()'的注释,以防万一你这样做的原因。 –

0

看看在php_rand.h中定义的RAND_RANGE宏。它会对输入值进行一些额外的置换/扰乱处理,以使其适合您指定的范围。

如果你真的想要的rand()函数返回3264即使不传递给兰特(参数范围内适合),删除rand.c块:

if (argc == 2) { 
    RAND_RANGE(number, min, max, PHP_RAND_MAX); 
} 

如果仍想要考虑最小/最大值,如果指定不包含硬编码数字的最小/最大值,您将需要弄清楚实际执行的操作。