摘要:另一個(gè)說(shuō)明我叫它做宏。你可以為函數(shù)定義寫一個(gè)宏事實(shí)上,就是這么做的,但我們會(huì)在后面的文章中深入了解這個(gè)。我想說(shuō)的是,宏允許在預(yù)處理編譯時(shí)使用更簡(jiǎn)單的代碼?;蛘哒f(shuō)頭文件定義了在文件中可以被其他文件看到的函數(shù),包括預(yù)處理宏。
文章來(lái)自:http://www.hoohack.me/2016/02/04/phps-source-code-for-php-developers-ch
原文:http://blog.ircmaxell.com/2012/03/phps-source-code-for-php-developers.html
作為一個(gè)開發(fā)者,我發(fā)現(xiàn)在我的日常工作中越來(lái)越多地查看PHP的源碼。在為了弄清楚奇怪的邊界問(wèn)題和為什么某些問(wèn)題應(yīng)該發(fā)生的卻沒(méi)有發(fā)生而去理解背后究竟發(fā)生了什么事情的時(shí)候非常有用。在文檔缺失、不完整或者錯(cuò)誤的情況下也很有用。因此,我已經(jīng)決定通過(guò)一系列的文章來(lái)分享我學(xué)到的知識(shí),給予PHP開發(fā)者們足夠的知識(shí)去真正閱讀PHP的C語(yǔ)言源碼。你并不需要有C語(yǔ)言的基礎(chǔ)(我們會(huì)總結(jié)一些基礎(chǔ)),但如果有的話會(huì)更有幫助。
這是這個(gè)系列的第一篇文章。在這篇文章,我們會(huì)談?wù)揚(yáng)HP程序的基礎(chǔ):在哪里找到它,基本的代碼結(jié)構(gòu)和一些最基礎(chǔ)的C語(yǔ)言概念。需要說(shuō)明的是,這一系列文章的目標(biāo)是獲得源碼的閱讀理解能力。這意味著為了過(guò)一下某些點(diǎn),某些概念會(huì)被簡(jiǎn)化而不是太復(fù)雜的描述。這不會(huì)給閱讀造成明顯的差異,但如果你想為源碼做貢獻(xiàn),則還有更多的知識(shí)需要補(bǔ)充。在我做簡(jiǎn)化的時(shí)候,我會(huì)盡量指出這些簡(jiǎn)化。
另外,這系列文章是基于5.4版本的源碼,在不同版本中,大部分概念都是一樣的,但這里,我們需要針對(duì)這次的文章有一個(gè)版本的定義(為了讓新的版本出來(lái)后接下來(lái)的文章更容易地遵循)。
那么,我們可以開始了吧?
在哪里找到PHP的源碼下載PHP源碼最簡(jiǎn)單的方式是通過(guò)PHP的SVN倉(cāng)庫(kù)。對(duì)于這此文章,我們檢出(check out)了5.4的分支。這對(duì)于成為PHP的前沿或者真正的開發(fā)PHP(解決bugs,實(shí)現(xiàn)特性等等)來(lái)說(shuō)是非常棒的。值得注意的是,PHP社區(qū)正在(這篇文章正在寫的時(shí)候)將源碼遷移到GIT倉(cāng)庫(kù)中。一旦遷移完成,我會(huì)更新這篇文章以達(dá)到標(biāo)準(zhǔn)。(譯者注:譯者翻譯的時(shí)候PHP已經(jīng)遷移到GIT倉(cāng)庫(kù)了)。
事實(shí)上,下載源碼對(duì)我們的目的來(lái)說(shuō)并不是真正的有用。我們不想編輯它,我們只是想使用它和跟蹤它是如何運(yùn)行的。我們可以下載它,然后導(dǎo)入到一個(gè)好的IDE中,在這些IDE中我們可以點(diǎn)擊跳到函數(shù)的定義和聲明,當(dāng)我發(fā)現(xiàn)這比想象中略困難。我有一個(gè)更好的解決方案。
事實(shí)證明,PHP社區(qū)在維護(hù)一個(gè)對(duì)于我們來(lái)說(shuō)一個(gè)非常好的工具。那就是lxr.php.net。這主要是一個(gè)自動(dòng)生成可搜索的源碼列表,而且有語(yǔ)法高亮和函數(shù)全部有鏈接的。這個(gè)是我?guī)缀踔挥脕?lái)瀏覽C源碼的工具,實(shí)在太棒(即使在我寫補(bǔ)丁的時(shí)候,我依然到lxr而不是我正在開發(fā)的代碼庫(kù))。我們還不會(huì)講到如何做更有效的搜索,但我們會(huì)在談?wù)揚(yáng)HP核心函數(shù)的時(shí)候講到。
從這里開始,我們將開始談?wù)揚(yáng)HP5.4。為了達(dá)到這目的,我們會(huì)使用這個(gè)lxr鏈接作為其他文章的基礎(chǔ)。當(dāng)我提到“5.4的根目錄”的時(shí)候,我就是說(shuō)這個(gè)頁(yè)面。
那么,既然我們可以查看源碼目錄了,那么我們來(lái)談?wù)勥@里面都有什么吧。
PHP源碼結(jié)構(gòu)那么,當(dāng)你查看列在5.4的根目錄的文件和目錄時(shí),還有很多可以研究。我希望你只關(guān)注兩個(gè)目錄:ext和Zend。其他的文件和目錄對(duì)于PHP擴(kuò)展和開發(fā)來(lái)說(shuō)很重要,但對(duì)于我們的目的來(lái)說(shuō),我們完全可以忽略它們。那么,為什么這兩個(gè)目錄那么重要呢?
PHP程序被分為,你猜對(duì)了,兩個(gè)主要的部分。第一部分是Zend引擎,控制PHP代碼運(yùn)行時(shí)候的運(yùn)行環(huán)境。它處理PHP提供的所有“語(yǔ)言層”的特性,包括:變量,表達(dá)式,語(yǔ)法解析,代碼執(zhí)行和錯(cuò)誤處理。沒(méi)有這個(gè)引擎,就沒(méi)有PHP。引擎的源碼放在了Zend目錄。
PHP第二個(gè)核心的部分,是包含在PHP里面的擴(kuò)展。這些擴(kuò)展包括我們可以在PHP調(diào)用的每一個(gè)核心函數(shù)(例如strpos,substr,array_diff,mysql_connect等等)。也包括核心的類(MySQLi,SplFixedArray,PDO等等)。
在核心代碼中,決定在哪里找到你想查看的功能最簡(jiǎn)單的方法是,查看PHP的文檔首頁(yè)。PHP的文檔也被分為兩個(gè)主要的部分(為了達(dá)到我們的目的),語(yǔ)言參考和函數(shù)參考。作為一個(gè)龐大的概括,如果你想查看的是在語(yǔ)言參考中的定義,很有可能可以在Zend文件夾找到。如果是在函數(shù)參考中,可以在ext文件夾中找到。
一些基本的C語(yǔ)言概念這部分不是為了成為C的入門,而是一個(gè)“讀者的配套指南”。有如下概念:
變量在C里面,變量是靜態(tài)和強(qiáng)類型的。這意味著變量必須要使用一個(gè)類型定義之后才能使用。一旦定義之后,你不能改變它的類型(你可以在之后轉(zhuǎn)換成其他類型,但你需要使用不同的變量來(lái)實(shí)現(xiàn))。因?yàn)?,在C語(yǔ)言里面,變量并不真實(shí)地存在。它們只是為了我們使用的方便的內(nèi)存地址的標(biāo)簽。正因?yàn)槿绱?,C語(yǔ)言沒(méi)有PHP中的引用。取而代之,它有指針。為了我們的目的,把指針想象成指向其他變量的變量。把它當(dāng)作PHP中變量的變量。
那么,通過(guò)上面的描述,我們來(lái)談?wù)撘幌伦兞康恼Z(yǔ)法。C語(yǔ)言沒(méi)有使用任何的前綴來(lái)標(biāo)識(shí)變量。因此,要說(shuō)出它們的不同的唯一方式(為了達(dá)到我們的目的)是查看它們的定義。如果你在函數(shù)的頂部(或者函數(shù)的聲明)看到在類型和空格之后的字符,那就是變量。一個(gè)要說(shuō)明的關(guān)鍵點(diǎn)是變量名前面可以有一個(gè)或這多個(gè)符號(hào)。星號(hào)(*)表明變量是指向某個(gè)類型的指針(一個(gè)引用)。兩個(gè)星號(hào)表明變量是指向指針的指針。三個(gè)星號(hào)表明變量是指向一個(gè)指向其他指針的指針。
這個(gè)間接尋址非常重要,因?yàn)镻HP內(nèi)部使用很多的雙層指針。這是因?yàn)橐嫘枰軌騻鬟f塊數(shù)據(jù)(PHP變量),和所有有趣的類型如PHP引用,寫時(shí)復(fù)制以及對(duì)象引用等等。因此,只要意識(shí)到**ptr意味著我們正使用兩層的引用(不是變量的引用,而是一個(gè)數(shù)據(jù)引用的引用)。這又一點(diǎn)迷惑,但如果引用對(duì)你來(lái)說(shuō)是完全新的知識(shí),我建議你閱讀一下這方面的知識(shí)(盡管我們的目的是不用必需閱讀C)。會(huì)有幫助的。
現(xiàn)在,另一個(gè)理解指針的事情是它們是如何在C的數(shù)組里應(yīng)用的(不是PHP的數(shù)組,而是C語(yǔ)言中的數(shù)組)。因?yàn)橹羔樖莾?nèi)存地址,我們可以通過(guò)分配一塊的內(nèi)存來(lái)定義一個(gè)數(shù)組,然后通過(guò)遞增指針來(lái)遍歷它。正常情況下,我們可以使用代表一個(gè)字符(8位)的C的數(shù)據(jù)類型char來(lái)存儲(chǔ)字符串中的一個(gè)字符。但我們也可以像使用數(shù)組那樣使用它來(lái)訪問(wèn)字符串后面的字節(jié)。因此,我們可以只在第一個(gè)字節(jié)里存儲(chǔ)一個(gè)指針而不是存儲(chǔ)正一個(gè)字符串在變量中。然后,我們可以遞增指針(增加它的內(nèi)存地址)來(lái)遍歷整個(gè)字符串。
char *foo = "test"; // foo 是指向"t"在內(nèi)存的片段保存"test"的指針 // 要訪問(wèn)"e",我們可以通過(guò)下面的方式: char e = foo[1]; char e = *(foo + 1); char e = *(++foo);
要另外閱讀C語(yǔ)言重點(diǎn)的變量和指針,查看這本很好的免費(fèi)書籍。
預(yù)處理說(shuō)明C在編譯之前使用一步叫做“預(yù)處理”的步驟。這一步包含優(yōu)化和根據(jù)你傳遞給編譯器的選項(xiàng)動(dòng)態(tài)使用部分代碼。我們將談?wù)搩蓚€(gè)主要的預(yù)處理器說(shuō)明:條件語(yǔ)句和宏。
條件語(yǔ)句允許代碼在編譯輸出或者不是基于定義時(shí)被引入。這看起來(lái)很像下面的例子。這允許不同的代碼根據(jù)不同的操作系統(tǒng)被使用(因此盡管它們使用不同的API,也可以在Windows和Linux中很好的使用)。另外,它允許一部分代碼被引入或者不是基于定義的指示。事實(shí)上,這是配置步驟中如何編譯PHP的執(zhí)行過(guò)程。
#define FOO 1 #if FOO Foo is defined and not 0 #else Foo is not defined or is 0 #endif #ifdef FOO Foo is defined #else Foo is not defined #endif
另一個(gè)說(shuō)明我叫它做宏。這是最簡(jiǎn)單簡(jiǎn)化代碼的迷你函數(shù)。它們不是真正的函數(shù),但是在編譯預(yù)處理是會(huì)執(zhí)行簡(jiǎn)單的文本替換。因此,宏不會(huì)真正地調(diào)用函數(shù)。你可以為函數(shù)定義寫一個(gè)宏(事實(shí)上,PHP就是這么做的,但我們會(huì)在后面的文章中深入了解這個(gè))。我想說(shuō)的是,宏允許在預(yù)處理編譯時(shí)使用更簡(jiǎn)單的代碼。
#define FOO(a) ((a) + 1) int b = FOO(1); // Converted to int b = 1 + 1源文件
最后這一部分,我們需要了解的是兩種在C源碼使用的類型的文件。主要有兩種文件:.c和.h。.c文件是包含了源碼準(zhǔn)備編譯的文件。通常來(lái)說(shuō),.c文件包含了不能分享到其他文件的私有函數(shù)的實(shí)現(xiàn)。.h(或者說(shuō)頭文件)定義了在.c文件中可以被其他文件看到的函數(shù),包括預(yù)處理宏。頭文件定義公共API的方式,是通過(guò)不使用函數(shù)體重新聲明函數(shù)的簽名(跟PHP中的接口和抽象方法相似)。這樣,源碼就可以通過(guò)頭文件鏈接在一起了。
下一部分這個(gè)系列的下一部分文章,我們即將討論內(nèi)部函數(shù)在C里面是怎么定義的。因此你可以跳到任意的內(nèi)部函數(shù)(比如strlen)查看它的定義和它是如何工作的。保持這個(gè)節(jié)奏。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/21345.html
摘要:文章來(lái)自原文歡迎來(lái)到給開發(fā)者的源碼系列的第二部分。是在內(nèi)部代表任意一個(gè)變量的定義。這種情況下函數(shù)會(huì)拋出警告,而此函數(shù)馬上返回會(huì)返回給的用戶層代碼。原因是,是少數(shù)通過(guò)而不是擴(kuò)展定義的函數(shù)。下一部分下一部分會(huì)再次發(fā)表在。 文章來(lái)自:http://www.hoohack.me/2016/02/10/understanding-phps-internal-function-definitio...
摘要:為了防止你錯(cuò)過(guò)了之前的文章,以下是鏈接第一部分給開發(fā)者的源碼源碼結(jié)構(gòu)第二部分理解內(nèi)部函數(shù)的定義第三部分的變量實(shí)現(xiàn)所有的東西都是哈希表基本上,里面的所有東西都是哈希表。哈希后的結(jié)果可以被作為正常的數(shù)組的鍵值又名為內(nèi)存塊。表示哈希表的容量。 文章來(lái)自:http://www.hoohack.me/2016/02/15/understanding-phps-internal-array-im...
摘要:文章來(lái)自原文在給開發(fā)者的源碼系列的第三篇文章,我們打算擴(kuò)展上一篇文章來(lái)幫助理解內(nèi)部是怎么工作的。進(jìn)入在的核心代碼中,變量被稱為。要轉(zhuǎn)換一個(gè)為值,就調(diào)用函數(shù)。有了這個(gè)東西,我們可以看到函數(shù)馬上調(diào)用函數(shù)。 文章來(lái)自:http://www.hoohack.me/2016/02/12/phps-source-code-for-php-developers-part3-variables-ch...
摘要:最近閑來(lái)無(wú)事,所以對(duì)這門語(yǔ)言進(jìn)行更深一層的了解,對(duì)源碼進(jìn)行一番研究,是如何執(zhí)行我們寫的腳本的。引擎是語(yǔ)言實(shí)現(xiàn)的最為重要的部分,是最基礎(chǔ)最核心的部分,它的源碼在目錄下,代碼從編譯到執(zhí)行都是由完成的,后面章節(jié)絕大部分的源碼分析都是針對(duì)的。 最近閑來(lái)無(wú)事,所以對(duì)PHP這門語(yǔ)言進(jìn)行更深一層的了解,對(duì)源碼進(jìn)行一番研究,是如何執(zhí)行我們寫的PHP腳本的。 1.1.3 PHP的相關(guān)組成 1.1.3.1...
閱讀 2013·2021-11-23 10:08
閱讀 2348·2021-11-22 15:25
閱讀 3282·2021-11-11 16:55
閱讀 781·2021-11-04 16:05
閱讀 2618·2021-09-10 10:51
閱讀 719·2019-08-29 15:38
閱讀 1593·2019-08-29 14:11
閱讀 3492·2019-08-29 12:42