### 結構體
#### zend_array
```c
// HashTable為zend_array的別名
typedef struct _zend_array HashTable;
// zend_array結構體
struct _zend_array {
zend_refcounted_h gc; // 引用計數
union {
struct {
ZEND_ENDIAN_LOHI_4(
zend_uchar flags, // 例如,HASH_FLAG_PACKED是否為packed array,HASH_FLAG_INITIALIZED是否初始化數組
zend_uchar nApplyCount,
zend_uchar nIteratorsCount,
zend_uchar consistency)
} v;
uint32_t flags;
} u;
uint32_t nTableMask; // 用于計算索引,例如 nIndex = h | ht->nTableMask (nTableMask是一個負值,packed array默認為-2,hash array為-8)
Bucket *arData; // bucket數組
uint32_t nNumUsed; // 已用bucket數
uint32_t nNumOfElements; // 已有元素數,nNumOfElements <= nNumUsed,因為刪除的并不是直接從arData中移除
uint32_t nTableSize; // 數組的大小,為2^n
uint32_t nInternalPointer; // 數值索引
zend_long nNextFreeElement;
dtor_func_t pDestructor;
};
```
數組使用哈希表(hashTable)來實現,哈希表即通過key-value訪問數據,這里的key是直接映射到內存地址,也就是說根據key可以直接獲得保存在內存的值(這種方式稱尋址技術);
數組的元素存在Bucket結構:
```c
//Bucket:散列表中存儲的元素
typedef struct _Bucket {
zval val; // 存儲的具體value,這里嵌入了一個zval,而不是一個指針
zend_ulong h; // key根據times 33計算得到的哈希值,或者是數值索引編號
zend_string *key; // 存儲元素的key
} Bucket;
```
### packed array和hash array
  packed array不需要索引表,空間和效率上優于hash array
- packed array可以簡單理解為數字索引數組(事實上數字索引是有序的,并且不能間隔太大,否則為轉為hash array)
- hash array可以理解為關聯數組
### 哈希沖突
  即不同的bucket.key經過哈希函數得到相同的值(key通過zend_string_hash_val(key)可以計算h的值),但這些值需要同時插入nIndex數組,
但出現沖突時將原有的arData[nIndex]的位置信息存儲到新插入的value的zval.u2.next中,再將新value的存儲地址更新到索引數組
### 數組操作API
- zend_hash_init 數組初始化,設定zend_array初始值
- zend_hash_index_insert
- zend_hash_find
- zend_hash_add_new 插入uninitialized_zval到zend_array
- zend_hash_packed_to_hash packed array轉為hash array
- zend_hash_rehash 生成新的HashTable(刪除標識為IS_UNDF的數據,有效數據重新聚合并更新插入索引表)
- zend_hash_del 刪除,不會真正刪除,只是標識,如zval.u1.v.type為IS_UNDF,只有在擴容或重建時才觸發刪除,
- zend_hash_xxx 插入或更新字符串key,key指向zend_string的指針
- zend_hash_str_xxx 插入或更新字符串key,key執行char的指針,需要len表示字符串長度
- zend_has_index_xxx 插入或更新數字key
- php
- 編譯安裝
- 基本概念
- 垃圾回收機制
- 生命周期
- zval底層實現
- c擴展開發
- gdb調試工具
- 自定義擴展簡單demo
- 鉤子函數
- 讀取php.ini配置
- 數組
- 函數
- 類
- yaf擴展底層源碼
- swoole擴展底層源碼
- memoryGlobal內存池
- swoole協程使用記錄
- 單點登錄sso原理
- compser使用
- session實現機制
- c & linux
- gcc
- 指針
- 結構體,聯合和位字段
- 宏定義井號說明
- printf家族函數和可變參數
- 共享函數
- 靜態庫和動態庫
- makefile自動化構建
- 信號一
- 信號二
- inotify監控文件事件
- socket編程
- 簡介
- UNIX DOMAIN
- Internet DOMAIN
- TCP/IP
- 文件IO多路復用
- 內存管理
- 進程組,會話和控制終端
- daemon守護進程
- 多進程
- 多線程
- 常用進制轉換
- go
- 入門知識
- 字節和整數裝換
- python
- redis
- 應用場景
- 消息隊列
- 熱點數據
- 掃碼登錄
- 訂閱發布
- 次數限制
- 搶購超賣
- 持久化機制
- mysql
- 工作流程
- MyISAM和InnoDB區別
- 用戶和權限管理
- 執行計劃
- sql優化
- 事務和鎖
- 慢查詢日志
- case...when...then...end用法
- sql
- 參考
- linux
- 內核參數優化
- 防火墻設置
- docker
- docker入門知識
- 算法
- 多維數組合
- DFA算法
- 紅包金額分配