【问题标题】:Modifying PHP rand function修改 PHP rand 函数
【发布时间】:2012-11-07 17:52:04
【问题描述】:

出于测试和学习的目的,我想修改https://github.com/php/php-src:ext/standard/rand.c中的php randmt_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 而没有范围参数?

【问题讨论】:

  • 这个问题不是 php 问题。
  • @Dagon 我错过了,感谢指正!

标签: c php-internals


【解决方案1】:

查看 php_rand.h 中定义的 RAND_RANGE 宏。它会对输入值进行一些额外的排列/加扰,以使其适合您指定的范围。

如果您真的希望 rand() 函数返回 3264,即使它不适合传递给 rand() 的参数,请在 rand.c 中删除此块:

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

如果您仍想考虑 min/max,则需要弄清楚如果您指定的 min/max 不包括硬编码的数字,您希望它实际做什么。

【讨论】:

    【解决方案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 本身的情况下完成。

    【讨论】:

    • 非常感谢!我修改了 PHP_FUNCTION(rand) 并且它起作用了。我将使用该函数而不是 php_rand。
    • 其实修改的主要原因是没有给出固定的输出,我想在rand和mt_rand上测试一些东西。固定输出只是为了了解事情是如何工作的。
    • @acidrous 很公平,我想可能是这样,但我想确保我包含了关于 srand() 的评论,以防你这样做的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-20
    • 2014-02-21
    • 1970-01-01
    • 2012-02-05
    • 1970-01-01
    相关资源
    最近更新 更多