PHP空数组本质是哈希表,底层为初始容量8的HashTable,含arData内存块和nTableMask=7,支持动态扩容与整数/字符串键统一存储。

PHP空数组本质是哈希表,不是传统线性数组
PHP里所谓的“数组”,底层根本不是C语言那种连续内存块+固定长度的结构。它实际是一个有序映射(ordered map),由Zend引擎用哈希表(HashTable)实现。创建空数组时,PHP分配的是一个初始容量为8的哈希桶数组(arData),但这个“8”是内部实现细节,对开发者完全透明——你既看不到,也不需要关心,更不能在定义时写成 array(8) 这类语法。
两种主流写法:[] 和 array() 底层完全等价
无论写成 $arr = []; 还是 $arr = array();,Zend引擎执行的是同一套初始化流程:
- 分配一个
zend_array结构体,包含元信息(如nTableSize=8、nNumOfElements=0) - 申请一块连续内存作为
arData,可容纳8个Bucket(每个Bucket存键、值、哈希值等) - 设置哈希掩码
nTableMask = 7(即8-1),为后续位运算定位做准备 - 所有指针和计数器归零,逻辑上就是一个“空”的容器
动态扩容机制让大小变得无关紧要
数组为空时,它只是占了最小内存;一旦开始赋值,扩容自动触发:
- 插入第9个元素时,
nTableSize从8翻倍为16,arData内存重新分配并迁移数据 - 扩容始终按2的幂次增长(8→16→32→64…),保证哈希索引可用高效位运算
hash & nTableMask - 整数索引和字符串索引共用同一套哈希机制,键类型不影响扩容逻辑
为什么不能也不该指定大小?设计哲学使然
PHP数组的设计目标就是“无感伸缩”:
- 没有
array(100)或new Array(100)这类语法,因为这违背其动态映射本质 - 即使你手动预填100个空元素(如
array_fill(0,100,null)),底层仍是先建小表再多次扩容,效率反而更低 - 类型系统也印证这一点:
array是完整类型,?array只允许数组或null,不接受“带尺寸的数组类型”
不复杂但容易忽略
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











