This commit is contained in:
krahets
2023-11-09 05:13:54 +08:00
parent 9a09f9407e
commit 3f666fa676
85 changed files with 619 additions and 610 deletions

View File

@@ -3397,7 +3397,7 @@
<p>在计算机中,所有数据都是以二进制数的形式存储的,字符 <code>char</code> 也不例外。为了表示字符,我们需要建立一套“字符集”,规定每个字符和二进制数之间的一一对应关系。有了字符集之后,计算机就可以通过查表完成二进制数到字符的转换。</p>
<h2 id="341-ascii">3.4.1 &nbsp; ASCII 字符集<a class="headerlink" href="#341-ascii" title="Permanent link">&para;</a></h2>
<p>「ASCII 码」是最早出现的字符集,全称为“美国标准信息交换代码”。它使用 7 位二进制数(即一个字节的低 7 位)表示一个字符,最多能够表示 128 个不同的字符。如图 3-6 所示ASCII 码包括英文字母的大小写、数字 0 ~ 9、一些标点符号以及一些控制字符如换行符和制表符</p>
<p><a class="glightbox" href="../character_encoding.assets/ascii_table.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="ASCII 码" src="../character_encoding.assets/ascii_table.png" /></a></p>
<p><a class="glightbox" href="../character_encoding.assets/ascii_table.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="ASCII 码" class="animation-figure" src="../character_encoding.assets/ascii_table.png" /></a></p>
<p align="center"> 图 3-6 &nbsp; ASCII 码 </p>
<p>然而,<strong>ASCII 码仅能够表示英文</strong>。随着计算机的全球化诞生了一种能够表示更多语言的字符集「EASCII」。它在 ASCII 的 7 位基础上扩展到 8 位,能够表示 256 个不同的字符。</p>
@@ -3412,7 +3412,7 @@
<p>自 1991 年发布以来Unicode 不断扩充新的语言与字符。截止 2022 年 9 月Unicode 已经包含 149186 个字符,包括各种语言的字符、符号、甚至是表情符号等。在庞大的 Unicode 字符集中,常用的字符占用 2 字节,有些生僻的字符占 3 字节甚至 4 字节。</p>
<p>Unicode 是一种字符集标准,本质上是给每个字符分配一个编号(称为“码点”),<strong>但它并没有规定在计算机中如何存储这些字符码点</strong>。我们不禁会问:当多种长度的 Unicode 码点同时出现在同一个文本中时,系统如何解析字符?例如给定一个长度为 2 字节的编码,系统如何确认它是一个 2 字节的字符还是两个 1 字节的字符?</p>
<p>对于以上问题,<strong>一种直接的解决方案是将所有字符存储为等长的编码</strong>。如图 3-7 所示“Hello”中的每个字符占用 1 字节,“算法”中的每个字符占用 2 字节。我们可以通过高位填 0 将“Hello 算法”中的所有字符都编码为 2 字节长度。这样系统就可以每隔 2 字节解析一个字符,恢复出这个短语的内容了。</p>
<p><a class="glightbox" href="../character_encoding.assets/unicode_hello_algo.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Unicode 编码示例" src="../character_encoding.assets/unicode_hello_algo.png" /></a></p>
<p><a class="glightbox" href="../character_encoding.assets/unicode_hello_algo.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Unicode 编码示例" class="animation-figure" src="../character_encoding.assets/unicode_hello_algo.png" /></a></p>
<p align="center"> 图 3-7 &nbsp; Unicode 编码示例 </p>
<p>然而 ASCII 码已经向我们证明,编码英文只需要 1 字节。若采用上述方案,英文文本占用空间的大小将会是 ASCII 编码下大小的两倍,非常浪费内存空间。因此,我们需要一种更加高效的 Unicode 编码方法。</p>
@@ -3426,7 +3426,7 @@
<p>图 3-8 展示了“Hello算法”对应的 UTF-8 编码。观察发现,由于最高 <span class="arithmatex">\(n\)</span> 位都被设置为 <span class="arithmatex">\(1\)</span> ,因此系统可以通过读取最高位 <span class="arithmatex">\(1\)</span> 的个数来解析出字符的长度为 <span class="arithmatex">\(n\)</span></p>
<p>但为什么要将其余所有字节的高 2 位都设置为 <span class="arithmatex">\(10\)</span> 呢?实际上,这个 <span class="arithmatex">\(10\)</span> 能够起到校验符的作用。假设系统从一个错误的字节开始解析文本,字节头部的 <span class="arithmatex">\(10\)</span> 能够帮助系统快速的判断出异常。</p>
<p>之所以将 <span class="arithmatex">\(10\)</span> 当作校验符,是因为在 UTF-8 编码规则下,不可能有字符的最高两位是 <span class="arithmatex">\(10\)</span> 。这个结论可以用反证法来证明:假设一个字符的最高两位是 <span class="arithmatex">\(10\)</span> ,说明该字符的长度为 <span class="arithmatex">\(1\)</span> ,对应 ASCII 码。而 ASCII 码的最高位应该是 <span class="arithmatex">\(0\)</span> ,与假设矛盾。</p>
<p><a class="glightbox" href="../character_encoding.assets/utf-8_hello_algo.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="UTF-8 编码示例" src="../character_encoding.assets/utf-8_hello_algo.png" /></a></p>
<p><a class="glightbox" href="../character_encoding.assets/utf-8_hello_algo.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="UTF-8 编码示例" class="animation-figure" src="../character_encoding.assets/utf-8_hello_algo.png" /></a></p>
<p align="center"> 图 3-8 &nbsp; UTF-8 编码示例 </p>
<p>除了 UTF-8 之外,常见的编码方式还包括以下两种。</p>