2012-11-19 43 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); 
} 

如果仍想要考慮最小/最大值,如果指定不包含硬編碼數字的最小/最大值,您將需要弄清楚實際執行的操作。