php 7.4.32 中字符串封装在 zend_string 结构体中,含哈希值 h、长度 len 和柔性数组 val,内存布局为 gc_headerdata,支持写时复制、二进制安全且始终以 \0 结尾。

PHP 7.4.32 中字符串不是简单地用 char* 存储,而是封装在 zend_string 结构体中,由 Zend 内存管理器统一分配和维护。这种设计兼顾了性能、内存复用与安全。
zend_string 是 PHP 字符串的底层载体
它定义在 Zend/zend_types.h 中,核心字段包括:
-
zend_ulong h:字符串的哈希值(用于数组键查找等场景),首次访问时计算并缓存 -
size_t len:字符串实际长度(不含结尾\0) -
char val[]:柔性数组(C99 特性),紧接结构体之后存放字符数据,末尾自动补\0
整个结构体在 64 位系统上通常占 16 字节(h 占 8 字节,len 占 8 字节),然后才是字符串内容本身。例如 "abc" 的 zend_string 占用内存为 16 + 4 = 20 字节(含 \0)。
字符串内容与引用计数绑定zend_string 自带引用计数(GC_REFCOUNT),位于结构体头部之前——实际内存布局是:
[gc_header][zend_string][data...][\0]
其中 gc_header 包含 refcount 和类型标记,由 Zend GC 系统管理。这意味着:
- 多个
zval可共享同一个zend_string(如$a = "hello"; $b = $a;) - 修改字符串(如拼接、截取)会触发“写时复制”(copy-on-write),仅当
refcount > 1且内容要变时才真正复制
字符串不再隐式以 \0 结尾?不,它始终保证以 \0 结尾
虽然 PHP 字符串支持二进制安全(可含 \0 字节),但 zend_string->val 区域总是以 \0 结尾,且 len 精确记录有效长度。这使得它既能被 C 函数(如 strlen, strcmp)安全使用,又不会因中间 \0 被截断。
小字符串优化(Small String Optimization)未启用
PHP 7.4 没有像 C++ std::string 那样内置栈上存储小字符串。所有字符串都走堆分配,哪怕只有 1 字节——但通过 zend_string 的紧凑布局和引用计数,减少了重复分配开销。
与 zval 的关系很直接
当一个 zval 类型为 IS_STRING 时,其 value.str 字段就指向一个 zend_string *。这个指针不裸露给用户层,所有操作(如 strlen(), substr())都经由 Zend API(如 ZSTR_LEN(), ZSTR_VAL() 宏)安全访问。
不复杂但容易忽略
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











