zoukankan      html  css  js  c++  java
  • 字符串

    一。二进制安全

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

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

      举例 string.c 文件

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

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

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

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

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

       先查看 transfer_string.php 文件

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

     

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

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

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

      $a = 'abca' 存储为  $a = 'abc\0a' ,读取出来时不转义为 $a = 'abc\0a' ,长度为 6

      $b = "abca" 存储为 $b = "abc\0a" ,读取时会经过转义为  $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是不同的了,被分离出来了。

  • 相关阅读:
    Java实现 LeetCode 92 反转链表 II
    Java实现 LeetCode 92 反转链表 II
    Java实现 LeetCode 91 解码方法
    Java实现 LeetCode 91 解码方法
    Java实现 LeetCode 91 解码方法
    CDialogBar(对话条)和CReBar(伸缩条)的编程
    WinSock
    WinSock
    静态文本显示图标图片
    拆分窗口
  • 原文地址:https://www.cnblogs.com/GH-123/p/12159126.html
Copyright © 2011-2022 走看看