为何 php 手册里常常说某个函数是二进制安全的?咱们日常使用函数的时候也没发现有什么区别呀,那么二进制安全究竟是什么意思呢?php
<?php echo strlen("abc"); // 3 echo strlen("abc\0"); // 4 echo strlen("abc\0d"); // 5 echo strlen("abc\0def"); // 7
从上面的规律能够看出\0
被认为是一个字符,其实在上面的式子中\0
是一个ascii
字符。html
补课简单说明下 ascii 码咱们知道,计算机内部,全部信息最终都是一个二进制值。每个二进制位(bit)有0和1两种状态,所以八个二进制位就能够组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共能够用来表示256种不一样的状态,每个状态对应一个符号,就是256个符号,从
`00000000
到11111111
。segmentfault上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,作了统一规定。这被称为 ASCII 码,一直沿用至今。安全
man ascii
ascii 码前 33 个都是控制字符,好比咱们最熟悉的换行
,都是不可见的字符。bash
Oct Dec Hex Char Oct Dec Hex Char ──────────────────────────────────────────────────────────────────────── 000 0 00 NUL '\0' 100 64 40 @ 001 1 01 SOH (start of heading) 101 65 41 A 002 2 02 STX (start of text) 102 66 42 B 003 3 03 ETX (end of text) 103 67 43 C 004 4 04 EOT (end of transmission) 104 68 44 D 005 5 05 ENQ (enquiry) 105 69 45 E 006 6 06 ACK (acknowledge) 106 70 46 F 007 7 07 BEL '\a' (bell) 107 71 47 G 010 8 08 BS '\b' (backspace) 110 72 48 H 011 9 09 HT '\t' (horizontal tab) 111 73 49 I 012 10 0A LF '\n' (new line) 112 74 4A J
从上面的表中能够看到八进制012
和十六进制0A
都表示换行php7
echo "abc\012d"; echo "\n"; echo "abc\x0Ad"; echo "\n"; echo "abc\x0ad"; echo "\n"; echo "abc\nd"; echo "\n";
输出结果函数
abc d abc d abc d abc d
ascii 码第一个\0
则表示空字符
,因此执行学习
echo "abc\0d";
输出的就是abcd
。到这里上面的长度计算想必你们都弄明白了吧。ui
这里再留个你们一个思考题,strlen
和mb_strlen
有什么区别?
有兴趣的能够看看我这篇博客 https://mengkang.net/1129.html
#include <stdio.h> #include <string.h> int main(){ printf("%d\n",strlen("abc")); // 3 printf("%d\n",strlen("abc\0")); // 3 printf("%d\n",strlen("abc\0d")); // 3 printf("%d\n",strlen("abc\0def")); // 3 }
经过上面的例子能够观察到\0
及其之后都不在strlen
的计算范围内。在C语言里字符串都以\0
做为结束符。编码
#include <stdio.h> #include <string.h> int main(){ printf("%s\n","abc\0def"); // abc }
因此,由于字符串中间有\0
而影响程序逻辑和结果的状况,叫非二进制安全。
经过上面的两个实验发现只有C里面咱们才须要关注函数的二进制安全问题嘛,PHP 也会遇到相似的问题么?我怎么历来遇到过。下面两个例子。
<?php echo date("Y\0/m/d");
案例来源: https://stackoverflow.com/que...在线执行结果 https://3v4l.org/dqXhf
能够看出来date
函数是把入参"0/m/d"去掉了,不过在 php7 里修复了该问题。
<?php var_export(strcoll("a\0b","a")); var_export(strcmp("a\0b","a"));
这两个函数都是比较字符串“大小”,strcoll
会根据环境变量 LC_COLLATE
所指定的文字排列次序来比较两字符串的大小,默认 LC_COLLATE 为"POSIX"或"C",strcoll() 和 strcmp() 同样根据ASCII比较字符串大小。
strcoll 函数是官方手册在线说明了的非二进制安全的函数。 https://www.php.net/manual/en...
下面这个两个计算长度分辨是多少,下次课咱们一块儿分析 php 和 c 里面单引号和双引号的区别。
<?php echo strlen("123\0456"); echo strlen('123\0456');
你是否一直有这样的经历,使用 php 做为主语言开发已经有两三年了,一直想学习好 C 语言来做为本身的技术壁垒,却又难以突破。每次自学都是坚持几天,if else 数据类型看得倒背如流,看到晦涩的指针,深奥的内存,就偃旗息鼓。
又苦没有什么实战项目,最后只能放弃。往往过些时日,拒绝平庸的你,骚动的心里,又拿起那本被遗忘在角落的《21 天 C 语言从......》擦拭掉封面上的尘土,翻开了第一页,信誓旦旦,循环反复,但却依旧如初,一直在 C 语言大门以外徘徊,技术一直止步不前。
做为泥腿子的我,把本身学习过程当中总结的一些经验结合 php 语言特点和 c 语言对比学习,结合项目实战,总结成一个系列课,也许很是适合你,欢迎上车。《C 语言零基础 phper 翻身仗》https://segmentfault.com/ls/1...
也欢迎你们关注个人公众号,不发骚扰,只发干货原创文章