php7 字符串,php7字符串底层实现

本篇为《php7底层设计与源码实现》的读书笔记

php7 的字符串以zend_string 为载体,实现字符串的功能,还提供性能高效的smart_str

zend_string的结构体

struct _zend_string{

zend_refcounted_h gc;

zend_ulong h;

size_t len;

char val[1];

}

gc 用作引用计数

h 哈希值,存储字符串对应的哈希值,方便在操作的时候,直接读取

len 存储字符串长度

val 柔性数组,存储字符串值的地址

h 和 len 体现了空间换时间的做法。

zend_string 的api

zend_string_init 将一个普通的字符串初始化成zend_string。

zend_string_extend 对字符串进行扩容。

当扩容的字符串为普通字符串且refcount为1,直接调用perealloc进行扩容。

扩容的字符串refcount大于1 或者 为内部字符串,则先申请一块内存,把值拷贝到申请的内存。对于普通字符串,还需要对老字符串把refcount 减1。

字符串的二进制安全

传统的c字符串,在取值的时候,在遇到'\0'的时候,默认遇到字符串结束了。而在php中,因为存储了字符串的长度,所以会根据字符串长度来取值,还原字符串的内容。不会因为字符串中含有'\0'而提前结束。因而可以在字符串中存储各种格式的数据。

smart_str

type_def struct{

zend_string *s;

size_t a;

} smart_str;

当对字符串内容需要频繁扩容的时候。php提供了一种新的结构来处理。

通过一次性申请足够大的空间,保证在修改字符串的时候,尽量不需要重新申请空间。一般如果字符串len <256 则申请256,如果len>256则申请大于len 且为4096的最小整数倍内存。通过空间换时间,避免每次修改都需要取申请或者释放内存

字符串的赋值与写时分离

zend_string中有refcount用来做计算。当字符串被引用的时候,则用zend_reference 来使在字符串内容不变的情况下,只保存一份zend_string。具体实现如下图

32660e0287bb

字符串赋值

32660e0287bb

字符串引用

字符串类型

几个概念

字面量 代码中写死的变量值

标识符 变量名、函数名、方法名、类名

php已知字符串 保留字

保留字 无法用作函数名、类名等关键字 如 class public

php源码为了实现对字符串管理,对字符串进行分类。

IS_STR_PERSISTENT php的已知字符串,php代码中的字面量,标识符等字符串。开启opcache时,会常驻内存,如果未开启opcache则随着请求结束而被回收。

IS_STR_INTERNED 内部字符串

字符串类型转换

一般类型转换有两种隐式转换和显式转换

隐式转换由语言自身自动完成

直接的变量赋值操作 当把字符串类型的数据赋予一个变量,不管之前这个变量的类型是什么,此时该变量就是一个字符串变量。

运算式结果对变量的赋值操作 当表达式的操作数为同一数据类型,则只是改变表达式的结果,当表达式的操作数为不同数据类型,则会发生类型的自动转换。

显式类型转换

通过使用函数 或者是语言结构,完成对数据类型的转换。

如 (int) (float) 或者是 gettype settype函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值