【PHP核心學習】變數跟資料類型

來源:互聯網
上載者:User
【PHP核心學習】變數和資料類型
|=-----------------------------------------------------------------------=|

|=---------------------=[ PHP核心中的變數和資料類型]=--------------------=|

|=-----------------------------------------------------------------------=|

|=--------------------------=[ by d4shman ]=-----------------------------=|

|=-----------------------------------------------------------------------=|

|=-------------------------=[ May 6, 2014 ]=---------------------------=|

|=-----------------------------------------------------------------------=|


(_____ \| | | (_____ \ /\ / _____) | / )

_____) ) |__ | |_____) ) / \ | / | | / /

| ____/| __)| (_____ ( / /\ \| | | |< <

| | | | | | | | |__| | \_____| | \ \

|_| |_| |_| |_|______|\______)_| \_) (向phrack致敬!)


<--------------------------( Table of Contents )-------------------------->


0x01 變數的結構和類型

0x02 雜湊表--PHP的靈魂

0x03 常量

0x04 參考文獻

<------------------------------------------------------------------------->


/////

0x01 變數的結構和類型

/////

1.資料類型

1.1靜態類型語言(C/Java),編譯時間確定

1.2動態類型語言(php/python),運行時確定

1.3無類型語言(彙編),操作的底層儲存


2.php核心中所有的變數使用同一種資料結構zval來儲存,而這個結構同時表示php中各種資料類型,它不僅僅包含變數的值,也包含變數的類型。這就是php弱類型的核心。

php中的8中資料類型:

2.1標量類型: boolean, integer, float, string

2.2複合類型: array, object

2.3特殊類型: resource, null

3.zval結構體(在php源碼目錄下Zend/zend.h中定義):

struct _zval_struct{

/*Variable information*/

zvalue_value value /*value, 變數的值*/

zend_uint refcount__gc /*reference count, 引用計數器*/

zend_uchar type /*active type, 變數的類型*/

zend_uchar is_ref__gc; /*變數是否被引用*/

}


4.變數類型:

/*data types */

#define IS_NULL0

#define IS_LONG 1

#define IS_DOUBLE 2

#define IS_BOOL 3

#define IS_ARRAY4

#define IS_OBJECT5

#define IS_STRING 6

#define IS_RESOURCE7

#define IS_CONSTANT8

#define IS_CONSTANT_ARRAY9

#define IS_CALLABLE10

5.變數的值儲存

typedef union _zvalue_value {

long lval; /*long、bool、resource類型*/

double dval ;/*double 類型*/

struct {/*string 類型, len儲存了字串的長度*/

char *val;

int len;

} str;

HashTable *ht; /*數組, 用HashTable實現*/

zend_object_value obj; /*object 類型*/

} zvalue_value;

這裡之所以用共同體(union)是因為一個變數只可能有一種類型,符合共同體的特性,如果使用結構體則會浪費記憶體。

執行個體:建立一個值為10的整型變數lvar,用php指令碼的話很簡單,就是:$lvar = 10

而PHP核心中的實現可能就是類似下面這樣:

zval lval;

Z_TYPE(lvar) = IS_LONG;

Z_LVAL(lvar) = 10;

/////

0x02 雜湊表--PHP的靈魂

/////

1.為什麼用雜湊表

雜湊表通常提供CRUD(Create, Read, Update, Delete)操作,設計合理的雜湊表中,這些操作時間複雜度為O(1),這也是它被鐘愛的原因。

hash(key) -> index

2.雜湊表的實現:結構體 bucket和_hashtable組成了完整的HashTable。

首先看bucket結構體(定義在 Zend/zend_hash.h):

typedef struct bucket {

ulong h; /*hash值*/

uint nKeyLength;/*key的長度*/

void *pData;/*要儲存的記憶體塊地址,通常是malloc來的地址*/

void *pDataPtr;/*儲存指標資料,不經過malloc的指標,防止產生記憶體片段*/

struct bucket *pListNext; /*bucket中具有同一hash值的下一個元素*/

struct bucket *pListLast; /*bucket中具有同一hash值的上一個元素*/

struct bucket *pNext;/*雙向鏈表的下一個元素*/

struct bucket *pLast; /*雙向鏈表的上一個元素*/

const char *arKey;/*儲存key*/

} Bucket;

可以看出bucket是一個雙向鏈表,這是為瞭解決多個key衝突的問題(即演算法導論中的連結法)

再看_hashtable結構體:

typedef struct _hashtable {

uint nTableSize; /*bucket數組的大小*/

uint nTableMask;

uint nNumOfElements;/*HashTable中元素的個數*/

ulong nNextFreeElement;/*下一個可用的Bucket位置*/

Bucket *pInternalPointer/*遍曆HashTable元素*/

Bucket *pListHead;/*雙向鏈表表頭*/

Bucket *pListTail;/*雙向鏈表表尾*/

Bucket **arBuckets;/*Bucket數組*/

} HashTable;

========

此處為HashTable的結構圖

========


3.神奇的數字--33

見我原來的一篇部落格:http://blog.csdn.net/wusuopubupt/article/details/11479869

下面是PHP源碼中的一段注釋:

/*

* DJBX33A (Daniel J. Bernstein, Times 33 with Addition)

*

* This is Daniel J. Bernstein's popular `times 33' hash function as

* posted by him years ago on comp.lang.c. It basically uses a function

* like ``hash(i) = hash(i-1) * 33 + str[i]''. This is one of the best

* known hash functions for strings. Because it is both computed very

* fast and distributes very well.

*

* The magic of number 33, i.e. why it works better than many other

* constants, prime or not, has never been adequately explained by

* anyone. So I try an explanation: if one experimentally tests all

* multipliers between 1 and 256 (as RSE did now) one detects that even

* numbers are not useable at all. The remaining 128 odd numbers

* (except for the number 1) work more or less all equally well. They

* all distribute in an acceptable way and this way fill a hash table

* with an average percent of approx. 86%.

*

* If one compares the Chi^2 values of the variants, the number 33 not

* even has the best value. But the number 33 and a few other equally

* good numbers like 17, 31, 63, 127 and 129 have nevertheless a great

* advantage to the remaining numbers in the large set of possible

* multipliers: their multiply operation can be replaced by a faster

* operation based on just one shift plus either a single addition

* or subtraction operation. And because a hash function has to both

* distribute good _and_ has to be very fast to compute, those few

* numbers should be preferred and seems to be the reason why Daniel J.

* Bernstein also preferred it.

*

*

* -- Ralf S. Engelschall <[email protected]>

*/


4.雜湊表的操作介面(省略了部分參數)

初始化HashTable:int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction);

添加新hash值: int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData)

尋找hash: int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData);



/////

0x03 常量

/////

1.常量的內部結構

typedef struct _zend_constant {

zval value;

int flags; /*常量標記,如 CONST_PERSISTENT | CONST_CS */

char *name;

uint name_len;

int module_number;

} zend_constant;


2.define定義常量的過程

define的實現(定義在Zend/zend_builtin_functions.c),下面是部分核心代碼:

ZEND_FUNCTION(define)

{

/* 檢查常量名是否存在 */

if (zend_memnstr(name, "::", sizeof("::") - 1, name + name_len)) {

zend_error(E_WARNING, "Class constants cannot be defined or redefined");

RETURN_FALSE;

}

... // 類常量定義 此處不做介紹

c.value = *val;

zval_copy_ctor(&c.value);

if (val_free) {

zval_ptr_dtor(&val_free);

}

c.flags = case_sensitive; /* 大小寫敏感 */

c.name = zend_strndup(name, name_len);

c.name_len = name_len+1;

c.module_number = PHP_USER_CONSTANT;

if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) { /*註冊常量*/

RETURN_TRUE;

} else {

RETURN_FALSE;

}

}

3.魔術常量

PHP中的魔術常量,雖然叫做常量,但它們的值實際上隨它們在代碼中的位置而變化的。

__LINE__ 檔案中的當前行號。

__FILE__ 檔案的完整路徑和檔案名稱。如果用在被包含檔案中,則返回被包含的檔案名稱。

__DIR__ 檔案所在的目錄。如果用在被包括檔案中,則返回被包括的檔案所在的目錄。它等價於 dirname(__FILE__)。

__FUNCTION__函數名稱

__CLASS__ 類的名稱。類名包括其被聲明的作用地區(例如 Foo\Bar)。

__TRAIT__ Trait 的名字。Trait 名包括其被聲明的作用地區(例如 Foo\Bar)。

__METHOD__類的方法名

__NAMESPACE__當前命名空間的名稱(區分大小寫)。此常量是在編譯時間定義的(PHP 5.3.0 新增)。

PHP核心會在詞法解析時將這些常量的內容賦值進行替換,而不是在運行時進行分析。 舉個例子:

echo __LINE__;

function demo() {

echo __FUNCTION__;

}

demo();

?>

PHP已經在詞法解析時將這些常量換成了對應的值,以上的代碼可以看成如下的PHP代碼:

echo 2;

function demo() {

echo "demo";

}

demo();

?>


===========

此處涉及編譯原理知識,需補充。

===========

/////

0x04 參考文獻

/////


TIPI: http://www.php-internals.com/book/?p=chapt03/03-00-variable-and-data-types

1樓wusuopuBUPT昨天 14:06
本文github地址:https://github.com/wusuopubupt/phpLib/blob/master/PHP%E5%86%85%E6%A0%B8%E4%B8%AD%E7%9A%84%E5%8F%98%E9%87%8F%E5%92%8C%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.