導航:首頁 > 源碼編譯 > 函數源碼的詳解

函數源碼的詳解

發布時間:2025-07-14 07:42:26

『壹』 php7源碼之array_unique函數分析

以下源碼基於 PHP 7.3.8

array array_unique ( array array[,intarray[,intsort_flags = SORT_STRING ] ) (PHP 4 >= 4.0.1, PHP 5, PHP 7) array_unique — 移除數組中重復的值 參數說明: array:輸入的數組。 sort_flag:(可選)排序類型標記,用於修改排序行為,主要有以下值: SORT_REGULAR - 按照通常方法比較(不修改類型) SORT_NUMERIC - 按照數字形式比較 SORT_STRING - 按照字元串形式比較 SORT_LOCALE_STRING - 根據當前的本地化設置,按照字元串比較。

array_unique 函數的源代碼在 /ext/standard/array.c 文件中。由於篇幅過長,完整代碼不在這里貼出來了,可以參見 GitHub 貼出的源代碼。

定義變數

首先是定義變數,array_unique 函數默認使用 PHP_SORT_STRING 排序,PHP_SORT_STRING 在 /ext/standard/php_array.h 頭文件中定義。

可以看到和開頭PHP函數的sort_flag 參數默認的預定義常量 SORT_STRING 很像。

compare_func_t cmp 這行代碼沒看懂,不清楚是做什麼的。compare_func_t 在 /Zend/zend_types.h 中定義:應該是定義了一個指向int 型返回值且帶有兩個指針常量參數的函數指針類型,沒有查到相關資料,先擱著,繼續往下看。

參數解析

ZEND_PARSE_PARAMETERS_START(1, 2),第一個參數表示必傳參數個數,第二個參數表示最多參數個數,即該函數參數范圍是 1-2 個。

數組元素個數判斷

這段代碼很容易看懂,當數組為空或只有 1 個元素時,無需去重操作,直接將array 拷貝到新數組 return_value來返回即可。

分配持久化內存

這一步只有當sort_type 為 PHP_SORT_STRING 時才執行。在下面可以看到調用 zend_hash_init 初始化了 array,調用 zend_hash_destroy 釋放持久化的內存。

設置比較函數

進行具體比較順序控制的函數指針是cmp,是通過向 php_get_data_compare_func 傳入 sort_type 和 0 得到的,sort_type 也就是 SORT_STRING 這樣的標記。

php_get_data_compare_func 在 array.c 文件中定義(即與 array_unique 函數同一文件),代碼過長,這里只貼出默認標記為 SORT_STRING 的代碼:

在前面的代碼中,我們可以看到,cmp = php_get_data_compare_func(sort_type, 0); 的第二個參數,即參數 reverse 的值為 0,也就是當 sort_type 為 PHP_SORT_STRING 時,調用的是 php_array_data_compare_string 函數,即 SORT_STRING 採用 php_array_data_compare_string 進行比較。繼續展開 php_array_data_compare_string 函數:

可以得到這樣一條調用鏈:

string_compare_function 是一個 ZEND API,在 /Zend/zend_operators.c 中定義:

可以看到,SORT_STRING 使用 zend_binary_strcmp 函數進行字元串比較。下面的代碼是 zend_binary_strcmp 的實現(也在 /Zend/zend_operators.c 中):

上面的代碼是比較兩個字元串。也就是SORT_STRING 排序方式的底層實現是 C 語言的 memcmp,即它對兩個字元串從前往後,按照逐個位元組比較,一旦位元組有差異,就終止並比較出大小。

數組排序

這段代碼初始化一個新的數組,然後將值拷貝到新數組,然後調用zend_sort 排序函數對數組進行排序。排序演算法在 /Zend/zend_sort.c 中實現,注釋有這樣一句話:

Derived from LLVM's libc++ implementation of std::sort.

這個排序演算法是基於LLVM 的 libc++ 中的 std::sort 實現的,算是快排的優化版,當元素數小於等於16時有特殊的優化,當元素數小於等於 5 時直接通過 if else 嵌套判斷排序。代碼就不貼出來了。

數組去重

回到array_unique 上,繼續看代碼:

遍歷排序好的數組,然後刪除重復的元素。

眾周所知,快排的時間復雜度是O(nlogn),因此,array_unique 函數的時間復雜度是O(nlogn)。array_unique 底層調用了快排演算法,加大了函數運行的時間開銷,當數據量很大時,會導致整個函數的運行較慢。

閱讀全文

與函數源碼的詳解相關的資料

熱點內容
只讀或者加密不能復制 瀏覽:924
自貢壓縮機招聘 瀏覽:5
程序員與女友 瀏覽:456
紅旅app怎麼樣 瀏覽:950
雲伺服器vm 瀏覽:535
pdf劃詞 瀏覽:687
萬年歷雲伺服器 瀏覽:507
單片機2CF 瀏覽:191
手機能做單片機嗎 瀏覽:347
vrandroidsdk 瀏覽:406
安全管理隱患排查系統源碼 瀏覽:31
vim編譯器怎麼讀 瀏覽:463
網頁修改源碼怎麼進 瀏覽:158
12323違章查詢app從哪裡查詢呀 瀏覽:761
ui設計app如何適配 瀏覽:694
房地產公司有程序員嗎 瀏覽:305
java內存池 瀏覽:868
金盾加密器怎麼設置黑名單 瀏覽:595
壓縮卷磁碟上沒有足夠的空間完成此操作 瀏覽:371
kvm常用命令 瀏覽:621