字符串

Posted gh-123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字符串相关的知识,希望对你有一定的参考价值。

------------恢复内容开始------------

一。二进制安全

  数据写入时是什么样子,读出来就是什么样子,这称为二进制安全。

  c语言的字符串不是二进制安全的,以为结束符,只能存储文本数据,不能存储图片音频等二进制数据。

  举例 string.c 文件

技术图片

   运行后得出如下结果, a和b是相等的,长度是3,而显然a和b是不想等的,长度也应该为5,这是因为c的字符串以为结束符

技术图片

   php的字符串是二进制安全的,看一下PHP的代码,$a和$b是不想等的,而且长度为5

技术图片

   PHP实现二进制安全的主要原因是zend_string结构体的重新封装,直接以长度len来直接全部读取出来。

二。双引号和单引号转义的区别

  先看上面二进制安全的例子,同一个字符串,单引号和双引号得出的结果却不一样

技术图片

   先查看 transfer_string.php 文件

技术图片

   接着调试查看存储的值为: "<?php $a = ‘abca‘; $b = "abca"; " , 这里即为,"即为",也是字符,为空字符。

 技术图片

   在读取到存储的值后,会经过词法解释生成AST树,这里只简单说一下过程。

  在解释到单引号时,从第一个单引号读到下一个单引号结束,中间直接返回zend_string,即字符串。

  而双引号和单引号过程一样,但中间的字符会进入到zend_scan_escape_string来进行转义。即

  $a = ‘abca‘ 存储为  $a = ‘abca‘ ,读取出来时不转义为 $a = ‘abca‘ ,长度为 6

  $b = "abca" 存储为 $b = "abca" ,读取时会经过转义为  $b = "abca" , 长度为 5

  可自行百度转义表

三。双引号对变量的解析

  这里也涉及到词法解析生成AST树,不过多说明,过程和转义类似,单引号直接读,双引号中间会生成 ZEND_AST_ENCAPS_LIST 的AST节点。

四。字符串赋值引用计数的变化

  字符串存储是共用一块内存的,通过计数来标识有多少变量引用了这块内存的值。现在看一下哪些赋值会使引用计数发生变化(对照zval的图)

  1. 简单变量赋值不会发生计数,直接复制值,如 int/true/false/double/long/null等 可查看 https://www.cnblogs.com/GH-123/p/11901744.html 的整型

  2. 常量字符串赋值不会发生计数,直接复制值,且 z.value.str.gc.u.v.flags 会被标志为0来记录是常量字符串

  3. 引用赋值会发生计数,可查看 https://www.cnblogs.com/GH-123/p/11901744.html 的引用

  4. 临时字符串,对象,资源等复杂类型一定会用到引用计数

  5. 普通数组会用到引用计数,但 IS_ARRAY_IMMUTABLE (一旦创建就不可更改的数据) 不会用到引用计数

五。字符串的写时分离

  只有zval为string、array、resource时,才会有写时分离,对象、传址引用等不支持。

  多个变量共用同一块内存的值时,对其中一个变量进行写操作,就会触发写时分离,即重新复制一份数据给这个变量。这里会涉及到字符串的扩充,不细写

  可查看 https://www.cnblogs.com/GH-123/p/11901744.html 里的引用,按照14点来操作,可发现$c的存储值的地址和b以及c是不同的了,被分离出来了。

 

 

 

 

 

 

 

 

  

------------恢复内容结束------------

以上是关于字符串的主要内容,如果未能解决你的问题,请参考以下文章

第15章:字符串

什么是字符串常量和字符串变量啊???

neo4j字符串操作大全

java中怎么判断一个字符串数组中包含某个字符或字符串

PHP字符串函数

如何获取一个字符串在某个字符串的位置