内容简介:baiyan全部视频:源视频地址:
【PHP源码学习】2019-03-13 PHP 字符串笔记
baiyan
全部视频: https://segmentfault.com/a/11...
源视频地址: http://replay.xesv5.com/ll/24...
字符串的设计过程
- 在C99的柔性数组标准未发布之前,我们如果存储一个字符串,可以使用如下代码:
struct string{ ... int len; //存长度 char* val; //存真正的字符串值 };
-
那么我们发现,这样做有如下缺点:
-
- 访问字符串值的时候,需要先访问结构体,在访问指针所指向的内存空间,需要2次内存访问,效率低下。
- 释放字符串内存空间的时候,需要先释放char *val指针所指向的内存空间,再释放结构体本身的内存空间,效率同样低下,而且这两个操作顺序不能颠倒。
- 那么如何改进呢?很容易想到,我们将字符串值和结构体存储在一片连续的内存空间就可以了。这样的话,访问字符串与释放字符串的内存空间,均仅需1次内存访问,在C99柔性数组标准发布之前,改进代码的方式如下:
int main() { struct string{ int len; }; typedef struct string str; char *s = "he"; str *p = (str*)(malloc(sizeof(str) + strlen(s) + 1)); //分配足够存下一个字符串的结构体 p->len = strlen(s); memcpy(p + 1, s, strlen(s)); //将字符串拷贝到紧邻结构体的内存处 }
- 小插曲:这个代码的第一版,我还出现了一个指针加法的错误,见: 关于memcpy一个字符串到紧邻结构体内存空间处的疑问
- 我们利用gdb调试一下这段代码:
- 首先我们应该给这个结构体分配4 + 2 + 1 = 7字节的内存空间,但是由于内存对齐的原因,最终分配了8字节大小的空间。
- 结构体本身和len字段的地址均是0x602010,len字段的长度为4B,指针加上4B的len字段长度之后,就应该是字符串he的起始地址,即0x602014,将其强转为char *,发现正好就是我们存的字符串值"he"。注意不是p+4,而是p+1。因为 p+4 = p+4*sizeof(指针p的类型)
- 由于这样编写代码过于繁琐,所以C99干脆制定一个标准,使用柔性数组代替上述写法。其实使用的计算方法和上面一段代码是一样的,只不过换了一种简化的写法而已,这段代码最终内存中的存储情况如下:
PHP7中字符串的实现
- 借助上文讲到的字符串数据结构设计思想,PHP中是这样设计字符串的,它的结构体叫做zend_string:
struct _zend_string { zend_refcounted_h gc; /*引用计数,与垃圾回收相关,暂不展开*/ zend_ulong h; /* 冗余的hash值,计算数组key的哈希值时避免重复计算*/ size_t len; /* 长度 */ char val[1]; /* 柔性数组,真正存放字符串值 */ };
-
第一个问题:为什么要存长度len?不存长度,直接和 C语言 一样通过字符串的'0'来判断字符串结束不行吗?不行。这里有一个二进制安全的问题。
- 二进制安全:写入的数据和读出来的数据完全相同,就是二进制安全的。
- 假设你写入了一个字符串的内容为:hello0world,按照C语言的读取字符串的方法就会判定0是字符串结束的标志,读出来就是hello,这样读出来的数据就和写入的数据不一致,就是非二进制安全的。
- 如果存了长度,就不会管你是否有0,从头开始读字符串,一直读len长度为止即可。
- 第二个问题:最后一个字段改成char val[0]可以吗?可以。写成char val[1]是出于可移植性的考虑。有些编译器不支持[0]数组,可将其改成[]或[1]均可。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Redis 源码阅读:字符串
- Redis 字符串内部结构源码分析
- 字符串匹配算法介绍及js字符串indexOf源码探究
- 查找一个字符串中最长不含重复字符的子字符串,计算该最长子字符串的长度
- (三)C语言之字符串与字符串函数
- 算法笔记字符串处理问题H:编排字符串(2064)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Spring实战(第4版)
Craig Walls 沃尔斯 / 张卫滨 / 人民邮电出版社 / 2016-4-1 / CNY 89.00
《Spring实战(第4版)》是经典的、畅销的Spring学习和实践指南。 第4版针对Spring 4进行了全面更新。全书分为四部分。第1部分介绍Spring框架的核心知识。第二部分在此基础上介绍了如何使用Spring构建Web应用程序。第三部分告别前端,介绍了如何在应用程序的后端使用Spring。第四部分描述了如何使用Spring与其他的应用和服务进行集成。 《Spring实战(第4......一起来看看 《Spring实战(第4版)》 这本书的介绍吧!