日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

PHP內(nèi)核探索 —— 變量的類型:PHP弱類型變量特性是如何實現(xiàn)?

瀏覽:130日期:2022-09-16 14:37:55

所有的編程語言都要提供一種數(shù)據(jù)的存儲與檢索機制,PHP也不例外。其它語言大都需要在使用變量之前先定義,并且它的類型也是無法再次改變的,而PHP卻允許程序猿自由的使用變量而無須提前定義,甚至可以隨時隨意的對已存在的變量轉(zhuǎn)換成其它任何PHP支持的數(shù)據(jù)類型。在程序在運行的時候,PHP還會自動的根據(jù)需求轉(zhuǎn)換變量的類型。

如果你用過PHP,肯定體驗過PHP的弱類型的變量體系。眾所周知,PHP引擎是用C寫的,而C確實一種強類型的編程語言,PHP內(nèi)核中是如何用C來實現(xiàn)自己的這種弱類型特性的?下面談?wù)勛兞康念愋汀?/p>

PHP在內(nèi)核中是通過zval這個結(jié)構(gòu)體來存儲變量的,它的定義在Zend/zend.h文件里,簡短精煉,只有四個成員組成:

struct _zval_struct {zvalue_value value;/* 變量的值 */zend_uint refcount__gc;zend_uchar type;/* 變量當前的數(shù)據(jù)類型 */zend_uchar is_ref__gc;};typedef struct _zval_struct zval;//在Zend/zend_types.h里定義的:typedef unsigned int zend_uint;typedef unsigned char zend_uchar;

zval里的refcout__gc是zend_uint類型,也就是unsinged int型,is_ref__gc和type則是unsigned char型的。保存變量值的value則是zvalue_value類型(PHP5),它是一個Union,同樣定義在了Zend/zend.h文件里:

typedef union _zvalue_value {long lval;/* long value */double dval;/* double value */struct {char *val;int len;} str;HashTable *ht;/* hash table value */zend_object_value obj;} zvalue_value;

在以上實現(xiàn)的基礎(chǔ)上,PHP語言得以實現(xiàn)了8種數(shù)據(jù)類型,這些數(shù)據(jù)類型在內(nèi)核中的分別對應(yīng)于特定的常量,它們分別是:

常量名稱:IS_NULL第一次使用的變量如果沒有初始化過,則會自動的賦予這個變量,當然我們也可以在PHP語言中通過null這個常量來給予變量null類型的值。 這個類型的值只有一個 ,就是NULL,它和0與false是不同的。IS_BOOL布爾類型的變量有兩個值,true或者false。在PHP語言中,while、if等語句會自動的把表達式的值轉(zhuǎn)成這個類型的。IS_LONGPHP語言中的整型,在內(nèi)核中是通過所在操作系統(tǒng)的singed long數(shù)據(jù)類型來表示的。在最常見的32位操作系統(tǒng)中,它可以存儲從-2147483648 到 +2147483647范圍內(nèi)的任一整數(shù)。有一點需要注意的是,如果PHP語言中的整型變量超出最大值或者最小值,它并不會直接溢出,而是會被內(nèi)核轉(zhuǎn)換成IS_DOUBLE類型的值然后再參與計算。再者,因為使用了singed long來作為載體,所以這也就解釋了為什么PHP語言中的整型數(shù)據(jù)都是帶符號的了。

$a=2147483647;$a++;echo $a;//會正確的輸出2147483648;IS_DOUBLEPHP中的浮點數(shù)據(jù)是通過C語言中的singed double型變量來存儲的,這最終取決與所在操作系統(tǒng)的浮點型實現(xiàn)。 我們做為程序猿,應(yīng)該知道計算機是無法精準的表示浮點數(shù)的,而是采用了科學(xué)計數(shù)法來保存某個精度的浮點數(shù)。用科學(xué)計數(shù)法,計算機只用8位便可以保存2.225x10^(-308)1.798x10^308之間的浮點數(shù)。用計算機來處理浮點數(shù)簡直就是一場噩夢,十進制的0.5專成二進制是0.1,0.8轉(zhuǎn)換后是0.1100110011....。但是當我們從二進制轉(zhuǎn)換回來的時候,往往會發(fā)現(xiàn)并不能得到0.8。我們用1除以3這個例子來解釋這個現(xiàn)象:1/3=0.3333333333.....,它是一個無限循環(huán)小數(shù),但是計算機可能只能精確存儲到0.333333,當我們再乘以三時,其實計算機計算的數(shù)是0.333333*3=0.999999,而不是我們平時數(shù)學(xué)中所期盼的1.0.IS_STRINGPHP中最常用的數(shù)據(jù)類型——字符串,在內(nèi)存中的存儲和C差不多,就是一塊能夠放下這個變量所有字符的內(nèi)存,并且在這個變量的zval實現(xiàn)里會保存著指向這塊內(nèi)存的指針。與C不同的是,PHP內(nèi)核還同時在zval結(jié)構(gòu)里保存著這個字符串的實際長度,這個設(shè)計使PHP可以在字符串中嵌入‘0’字符,也使PHP的字符串是二進制安全的,可以安全的存儲二進制數(shù)據(jù)!本著艱苦樸素的作風,內(nèi)核只會為字符串申請它長度+1的內(nèi)存,最后一個字節(jié)存儲的是‘0’字符,所以在不需要二進制安全操作的時候,我們可以像通常C語言的概念那樣來使用它。IS_ARRAY數(shù)組是一個非常特殊的數(shù)據(jù)類型,它唯一的功能就是包含別的變量。在C語言中,一個數(shù)組只能承載一種類型的數(shù)據(jù),而PHP語言中的數(shù)組則靈活的多,它可以承載任意類型的數(shù)據(jù),這一切都是HashTable的功勞,每個HashTable中的元素都有兩部分組成:索引與值,每個元素的值都是一個獨立的zval(確切的說應(yīng)該是指向某個zval的指針)。IS_OBJECT和數(shù)組一樣,對象也是用來存儲復(fù)合數(shù)據(jù)的,但是與數(shù)組不同的是,對象還需要保存以下信息:方法、訪問權(quán)限、類常量以及其它的處理邏輯。相對與zend engine V1,V2中的對象實現(xiàn)已經(jīng)被徹底修改,所以我們PHP擴展開發(fā)者如果需要自己的擴展支持面向?qū)ο蟮墓ぷ鞣绞剑瑒t應(yīng)該對PHP5和PHP4分別對待!IS_RESOURCE有一些數(shù)據(jù)的內(nèi)容可能無法直接呈現(xiàn)給PHP用戶的,比如與某臺mysql服務(wù)器的鏈接,或者直接呈現(xiàn)出來也沒有什么意義。但用戶還需要這類數(shù)據(jù),因此PHP中提供了一種名為Resource(資源)的數(shù)據(jù)類型。有關(guān)這個數(shù)據(jù)類型的事宜將在第九章中介紹,現(xiàn)在我們只要知道有這么一種數(shù)據(jù)類型就行了。

zval結(jié)構(gòu)體里的type成員的值便是以上某個IS_*常量之一。內(nèi)核通過檢測變量的這個成員值來知道他是什么類型的數(shù)據(jù)并做相應(yīng)的后續(xù)處理。

如果要我們檢測一個變量的類型,最直接的辦法便是去讀取它的type成員的值:

void describe_zval(zval *foo){if (foo->type == IS_NULL){php_printf('這個變量的數(shù)據(jù)類型是: NULL'); } else {php_printf('這個變量的數(shù)據(jù)類型不是NULL,這種數(shù)據(jù)類型對應(yīng)的數(shù)字是: %d', foo->type); }}

上述做法看起來沒有錯誤,但它是一種被強烈禁止一種做法!

PHP內(nèi)核以后可能會修改變量的實現(xiàn)方式,所以檢測type的方法可能在以后就不能用了。為了解決這個兼容問題,zend頭文件中定義了大量的宏,供我們檢測、操作變量使用,使用這些宏不但讓我們的程序更易讀,還具有更好的兼容性。這里我們用Z_TYPE_P()宏來改寫上面那個程序。

void describe_zval(zval *foo){ if ( Z_TYPE_P(foo) == IS_NULL ) {php_printf('這個變量的數(shù)據(jù)類型是: NULL'); } else {php_printf('這個變量的數(shù)據(jù)類型不是NULL,這種數(shù)據(jù)類型對應(yīng)的數(shù)字是: %d', foo->type); }}

php_printf()函數(shù)是內(nèi)核對printf()函數(shù)的一層封裝,我們可以像使用printf()函數(shù)那樣使用它。

以_P一個p結(jié)尾的宏的參數(shù)大多是*zval型變量,此外獲取變量類型的宏還有兩個,分別是Z_TYPE和Z_TYPE_PP,前者的參數(shù)是zval型,而后者的參數(shù)則是**zval。這樣我們便可以猜測一下php內(nèi)核是如何實現(xiàn)gettype這個函數(shù)了,代碼如下:

//開始定義php語言中的函數(shù)gettypePHP_FUNCTION(gettype){//這個arg間接指向就是我們傳給gettype函數(shù)的參數(shù)。是一個zval**結(jié)構(gòu)//所以我們要對他使用__PP后綴的宏。zval **arg;//這個if的操作主要是讓arg指向參數(shù)~if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 'Z', &arg) == FAILURE) {return;}//調(diào)用Z_TYPE_PP宏來獲取arg指向zval的類型。//然后是一個switch結(jié)構(gòu),RETVAL_STRING宏代表這gettype函數(shù)返回的字符串類型的值switch (Z_TYPE_PP(arg)) {case IS_NULL:RETVAL_STRING('NULL', 1);break;case IS_BOOL:RETVAL_STRING('boolean', 1);break;case IS_LONG:RETVAL_STRING('integer', 1);break;case IS_DOUBLE:RETVAL_STRING('double', 1);break;case IS_STRING:RETVAL_STRING('string', 1);break;case IS_ARRAY:RETVAL_STRING('array', 1);break;case IS_OBJECT:RETVAL_STRING('object', 1);break;case IS_RESOURCE:{char *type_name;type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(arg) TSRMLS_CC);if (type_name) {RETVAL_STRING('resource', 1);break;}}default:RETVAL_STRING('unknown type', 1);}}

以上三個宏的定義在Zend/zend_operators.h里,定義分別是:

#define Z_TYPE(zval) (zval).type #define Z_TYPE_P(zval_p) Z_TYPE(*zval_p) #define Z_TYPE_PP(zval_pp) Z_TYPE(**zval_pp)

標簽: PHP
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品入口久久| 国产中文一区| 在线国产日韩| 久久最新视频| 免费人成网站在线观看欧美高清| 午夜在线视频观看日韩17c| 最新亚洲一区| 亚洲午夜久久| 日韩欧美精品一区二区综合视频| 日韩精品欧美大片| 国产精品久久久网站| 国产精品白浆| 福利一区和二区| 欧美精品资源| 亚洲一区欧美激情| 黑丝一区二区| 亚洲一区二区三区高清| 中文字幕免费精品| 国产毛片精品久久| 久久中文字幕一区二区| 韩国久久久久久| 午夜电影亚洲| 日韩精品三级| 精品视频高潮| 尤物tv在线精品| 亚洲a成人v| 国产精品午夜一区二区三区| 精品美女视频 | 国产亚洲一区在线| 在线观看亚洲精品福利片| 日韩黄色免费网站| 国产精品777777在线播放| 国产精品成久久久久| 香蕉国产精品| 日韩欧美2区| 福利一区在线| 午夜久久美女| 日本国产欧美| 精品国产日韩欧美精品国产欧美日韩一区二区三区 | 免费久久99精品国产| 欧美精品中文| 日韩精品免费一区二区在线观看 | 综合一区二区三区| 麻豆国产精品777777在线| 久久人人88| 日本不卡不码高清免费观看| 久久爱www.| 欧美va天堂在线| 国产精品一在线观看| 久久男女视频| 91精品国产自产观看在线| 日韩电影在线视频| 日本在线观看不卡视频| 欧美精品日日操| 97se亚洲| 国产99精品| 国产精品嫩草影院在线看| 激情六月综合| 精品国内亚洲2022精品成人| 欧美中文字幕| 亚洲欧洲美洲av| 亚洲精品黄色| 亚洲一级影院| 黄色欧美在线| 色婷婷成人网| 五月精品视频| 国产一区二区三区四区五区| 久久午夜精品| 亚洲爱爱视频| 免费日韩一区二区三区| 中文字幕日韩亚洲| 九九久久婷婷| 精品国产一区二区三区av片| 亚洲日本国产| 欧美中文字幕一区二区| 精品亚洲二区| 亚洲精品一级| 欧美在线亚洲| 日韩中文首页| 麻豆国产精品一区二区三区 | 美女久久网站| 99久久夜色精品国产亚洲1000部| 麻豆久久久久久| 日本久久一区| 蜜臀久久久久久久| 久久香蕉国产| 国产网站在线| 欧美激情视频一区二区三区免费 | 不卡中文一二三区| 国产精品yjizz视频网| 国产毛片久久久| 婷婷精品在线| 亚洲一区日韩| 亚洲电影在线一区二区三区| 欧美一区久久久| 久久精品网址| 国产精品115| 久久国内精品| 三级久久三级久久久| 日韩精品一级二级| 国产精品88久久久久久| 91精品国产91久久久久久黑人| 国产成人久久精品一区二区三区| 91亚洲无吗| 亚洲精品高潮| 亚洲人亚洲人色久| 亚洲综合图色| 久久精品999| 久久免费福利| 色在线视频观看| 亚洲a在线视频| 亚洲黄页一区| 中文字幕视频精品一区二区三区| 日韩动漫一区| 国产一区二区三区四区| 久久久夜精品| 日韩一区二区久久| 亚洲精品观看| 日韩精品视频中文字幕| 国产精品久久| 欧美羞羞视频| 黄色成人精品网站| 日韩精品免费视频人成| 久久影院一区二区三区| 日韩欧美精品| 麻豆9191精品国产| 91欧美极品| 成人在线黄色| 欧美一区二区三区高清视频| 香蕉久久久久久久av网站| 一区二区亚洲视频| 国产精品一区二区三区av| 新版的欧美在线视频| 女人天堂亚洲aⅴ在线观看| 亚州av一区| 91免费精品| 日韩中文字幕区一区有砖一区| 国产另类在线| 久久人人97超碰国产公开结果| 蜜桃av一区二区| 麻豆国产91在线播放| 欧美日韩激情| 国产乱码精品一区二区三区四区 | 亚洲成人不卡| 中文字幕乱码亚洲无线精品一区| 麻豆精品新av中文字幕| 国产综合婷婷| 国产欧美日韩一区二区三区四区| 国产一二在线播放| 视频一区二区欧美| 精品一区二区三区中文字幕| 欧美日韩国产高清| 国产欧美日韩综合一区在线播放| 欧美黑人做爰爽爽爽| 在线手机中文字幕| 欧美在线亚洲| 日韩在线黄色| 精品香蕉视频| 午夜精品影院| 91精品视频一区二区| 岛国av免费在线观看| 欧美中文字幕一区二区| 在线精品国产亚洲| 国产精品magnet| 欧美成a人国产精品高清乱码在线观看片在线观看久 | 欧美激情另类| 亚洲综合精品四区| 国产精品丝袜在线播放| 国产精品99一区二区三| 欧美日一区二区| 日韩精品免费一区二区夜夜嗨| 成人国产精品一区二区免费麻豆| 亚洲成人日韩| 国产精品a久久久久| 欧美不卡在线| 国产亚洲观看| 亚洲福利专区| 亚洲a成人v| 国产综合色区在线观看| 一区二区三区国产在线| 久久免费福利| 亚洲欧美日韩国产综合精品二区| 国产精品分类| 日本不卡视频一二三区| 精品国产99| 国产日韩欧美一区| 视频一区二区三区中文字幕| 日韩中文影院| 精品国产欧美日韩| 91国内精品| 喷白浆一区二区| 亚洲性色视频| 日韩啪啪电影网| 精品亚洲成人| 国产日产一区| 中文不卡在线| 夜夜嗨av一区二区三区网站四季av| 亚洲国产欧美日本视频| 国产日韩一区二区三区在线播放| 日韩一级不卡|