补课大略解释下 ascii 码

我们知道,打算机内部,所有信息终极都是一个二进制值。
每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。
也便是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,便是256个符号,从00000000到11111111。

上个世纪60年代,美国制订了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。
这被称为 ASCII 码,一贯沿用至今。

phpstx为什么php手册里经常说某个字符串函数是二进制平安的 HTML

man ascii

ascii 码前 33 个都是掌握字符,比如我们最熟习的换行,都是不可见的字符。

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都表示换行

echo \"大众abc\012d\公众;echo \"大众\n\"大众;echo \公众abc\x0Ad\公众;echo \"大众\n\"大众;echo \公众abc\x0ad\公众;echo \公众\n\"大众;echo \"大众abc\nd\"大众;echo \"大众\n\公众;

输出结果

abcdabcdabcdabcd

ascii 码第一个\0则表示空字符,以是实行

echo \"大众abc\0d\公众;

输出的便是abcd。
到这里上面的长度打算想必大家都弄明白了吧。

这里再留个大家一个思考题,strlen和mb_strlen有什么差异?

有兴趣的可以看看我这篇博客 https://mengkang.net/1129.html

C 实验

#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 也会碰着类似的问题么?我怎么从来碰着过。
下面两个例子。

案例1

<?phpecho date(\"大众Y\0/m/d\"大众);

案例来源:https://stackoverflow.com/questions/36933837/why-are-there-binary-safe-and-binary-unsafe-functions-in-php

在线实行结果 https://3v4l.org/dqXhf

可以看出来date函数是把入参\"大众0/m/d\"大众去掉了,不过在 php7 里修复了该问题。

案例2

<?phpvar_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/function.strcoll.php

课后思考

下面这个两个打算长度分辨是多少,下次课我们一起剖析 php 和 c 里面单引号和双引号的差异。

<?phpecho strlen(\公众123\0456\"大众);echo strlen('123\0456');

本文为云栖社区原创内容,未经许可不得转载。