【转】刨根究底字符编码之九——字符编码方案的演变与字节序

字符编码方案的演变与字节序

 

一、字符编码方案的演变

1.

根据前面的介绍,对于字符编码方案的演变,我们大致上可简单地划分为三个阶段:

  ① ASCII编码方案阶段 → ② ANSI编码方案阶段 → ③ Unicode/UCS编码方案阶段。

在第一个阶段的ASCII编码方案阶段,ASCII编码方案主要适用于美国(与美国同文的英国大致上也适用)。

后来计算机发展到欧洲各国以及世界各地,开始发展到了作为第二阶段的ANSI编码方案阶段,各个国家和地区先后各自制定了既兼容ASCII但又互不兼容的ANSI编码方案。

ANSI编码方案阶段的各自为政,为世界各个国家和地区基于计算机的信息交流带来了极大的不便,痛定思痛之余,终于通过Unicode/UCS编码方案的制定发展到了第三阶段,最终Unicode编码方案胜出。

2.

前文已经提及,编号字符集CCS(简称字符集)与字符编码方式CEF(简称编码方式)这两个概念,在早期阶段(主要是ASCII编码方案阶段和ANSI编码方案阶段)并没有必要严格区分。

在Unicode编码方案出现之前,字符集及其具体的编码方式是绑定耦合在一起的,因此,“字符集”、“编码”或“编码方式”甚至“编码方案”这几个概念经常相互指代、彼此混用。

比如,字符集里的字符编号(即码点编号)在很多文章里也称之为字符编码、字符码、码点、码位、码点值、码值等,字符编码也称之为编码实现、编码方案、编码方式、编码格式、编码形式、内码、编码值、码值(你没看错,字符编号与字符编码都有可能被简称为“码值”,头大了吧),等等,非常混乱。

3.

对于ASCII、GB2312、GBK、GB18030、Big5之类采用传统字符编码模型的历史遗留方案来说,由于基本上一个字符集只使用一种编码方式,因此这种混用问题还不大。

但在Unicode这样采用现代字符编码模型的全新方案出现之后,很多人受上述这些历史遗留方案的影响,从而无法正确地理解字符集和编码方式之间的关系,这导致了概念混乱,引起了大量误解。

然而,对于采用现代字符编码模型的Unicode编码方案来说,字符集和编码方式是必须明确区分的。从软件工程的角度来讲,传统字符编码模型中紧密绑定耦合在一起的字符集及编码方式这两个概念,在现代字符编码模型中被分离解耦了,而这种解耦带来了极大的灵活性。

这意味着,对于采用现代字符编码模型的同一个字符集,可以采用多个不同的编码方式对其字符编号进行编码。也因此,作为同一个Unicode字符集,目前就定义了UTF-8、UTF-16和UTF-32等多种可选的编码方式(注:UTF,即Unicode/UCS Transformation Format,Unicode/UCS转换格式)。

4.

所以,在如今字符编码方案的第三阶段,用Unicode来称呼一个编码方式已不合适,并且容易产生误解,引发混乱和导致困惑,而应该用UTF-8、UTF-16和UTF-32来称呼编码方式,以Unicode来称呼字符集,将包括Unicode字符集以及各UTF编码方式等在内的整体称之为字符编码方案或字符编码系统或字符编码标准。

另外,同一字符编码方式CEF的码元序列,在计算机实际处理、存储和传输时,还需再次编码转换为字符编码模式CES的字节序列。

字符编码方式CEF的码元序列可理解为字符编码在数学层面上的逻辑表示形式;相对而言,字符编码模式CES的字节序列则可理解为字符编码在计算机实现中的物理表示形式

而字节序列(Byte Sequence),则涉及到了不同的字节序(Byte-Order,主要分为大端序Big-Endian、小端序Little-Endian)。

 

二、字节序

1.

字节序,又称字节顺序,其英文为Byte-Order;另外英文中还可称为Endianness,因此也翻译为端序。

Endianness这个词,源自于1726年Jonathan Swift的名著:Gulliver's Travels(格列佛游记)。在书中有一个童话故事,大意是指Lilliput小人国的国王下了一道指令,规定其人民在剥水煮蛋时必须从little-end(小端)开始剥。这个规定惹恼了一群觉得应该要从big-end(大端)开始剥的人。事情发展到后来演变成了一场战争。后来,支持小端的人被称为little-endian,反之则被称为big-endian(在英语中后缀“-ian”表示“xx人”之意)。

 

1980年,Danny Cohen在他的论文“On Holy Wars and a Plea for Peace”中,第一次使用了Big-endian和Little-endian这两个术语,最终它们成为了异构计算机系统之间进行通讯、交换数据时所要考虑的极其重要的一个问题。

(注:所谓异构是指不同架构、不同结构、不同构造等,而这里的异构计算机系统,主要指的是采用不同CPU和/或不同操作系统的计算机系统。)

2.

为什么会存在字节序的问题?

当然不会是像童话故事里那样出于“无厘头”的原因,而是因为历史上设计不同计算机系统的人在当时基于各自的理由和原因(这里的理由和原因网上存在着各种不同的说法,但也或许根本就没有具体理由和原因,只是设计人员的个人偏好,甚至是随意决定的),在各自计算机系统的设计上作出了不同的选择。

字节序共分为三种:

  大端序BE(Big-Endian),也称高尾端序;

  小端序LE(Little-Endian),也称为低尾端序;

  中间序ME(Middle-Endian),也称为混合序,不太常用,本文不作介绍。

3.

字节序,具体来说,就是多字节数据(大于一个字节的数据)在计算机中存储、读取时其各个字节的排列顺序。

字节序也被称为端序,这里的“端”,是指多字节数据中位于两端的字节,很多情况下还特指尾端字节(也称为小端字节)。

所谓尾端字节或小端字节,假设按照人对文字通常从左到右(或从上到下)的读写顺序来看的话,多字节数据位于右端(或下端)的低位字节就是尾端字节或小端字节,而将位于左端(或上端)的高位字节称为头端字节或大端字节。

当然,如果不按照通常从左到右(或从上到下)的顺序,而是按照从右到左(或从下到上)的顺序,那么多字节数据位于右端(或上端)的高位字节就是头端字节或大端字节,而将位于左端(或下端)的低位字节称为尾端字节或小端字节。

可见,不论读写顺序是从左到右(或从上到下),还是从右到左(或从下到上),所谓大端、头端,指的是多字节数据中,代表更大数值的那个字节所在的那一端,而相反的那一端则是小端、尾端。

4.

而要彻底讲清楚大端序(高尾端序)、小端序(低尾端序),则需要从人读写二进制数的方向和内存地址的增长方向两者相结合讲起:

人读写二进制数的方向为(这是确定不变的):左--->右,大端/头端/高位--->小端/尾端/低位;或上--->下,大端/头端/高位--->小端/尾端/低位;

内存地址的增长方向则为(这是确定不变的):左--->右,低地址--->高地址;或上--->下,低地址--->高地址。

不过,计算机在内存中存取数据的方向则不是确定不变的,而是分为两种(注意,由于人的读写方向和内存地址增长方向是确定不变的,因此这里指的是计算机在内存中“书写”或阅读数据的方向):

1) 左--->右,大端/头端/高位--->小端/尾端/低位;或上--->下,大端/头端/高位--->小端/尾端/低位;

这种情况下,站在人的读写方向和内存地址增长方向(这两者的方向刚好一致)的角度来看,则是:大端在左(或在上),所以称之为大端序;或者说尾端在内存高地址,所以称之为高尾端序(即内存高地址存放多字节数据的尾端字节的字节顺序)。

2) 右--->左,大端/头端/高位--->小端/尾端/低位;或下--->上,大端/头端/高位--->小端/尾端/低位。

这种情况下,站在人的读写方向和内存地址增长方向(这两者的方向刚好一致)的角度来看,则是:小端在左(或在上),所以称之为小端序;或者说尾端在内存低地址,所以称之为低尾端序(即内存低地址存放多字节数据的尾端字节的字节顺序)。

【特别提示:大端序、小端序特别容易搞混,不好记忆;因此,建议使用高尾端序、低尾端序,本人是按下面这个方法来记忆的,很容易记住:存储的数据分头和尾——左头右尾,内存的地址分低和高——左低右高;因此,“高尾端”表示内存的地址存储数据的尾端,“低尾端”表示内存的地址存储数据的尾端。】

 

5.

注意,这里的“数据”指的是数据类型意义上的数据,因此,准确地说字节序只跟多字节的整型数据类型有关,比如int、short、long型;跟单字节的整型数据类型byte无关。

那么,为什么就只跟多字节的整型数据有关,而跟单字节的整型数据无关呢?

因为在现代计算机中,字节是计算机数据存储的基本单位,对于整体上的单一字节(a byte),涉及到的是其8个比特位的顺序(即位序、比特序,一般直接由硬件处理,程序员大致了解即可,这里不深入探讨),显然不存在字节序问题。

然而,对于在数据类型这个逻辑意义上作为一个整体的多字节数据而言,它是由计算机物理意义上各个可被单独寻址的字节所组成的(处理器寻址的最小单位一般是1个字节),由于历史的原因,其各个字节的存储顺序在不同的系统平台(包括CPU和操作系统)上是不同的。

6.

也就是说,如果计算机处理的数据是逻辑意义上的单字节数据类型(byte),是不存在字节序问题的,因为计算机物理意义上单独寻址的最小单位刚好也是字节,单个字节已经是处理器寻址的最小单位以及存储和传输的最小单元了,存储时单字节数据类型直接进行,读取时也不存在根据前后2个字节才能解析出其值的情况,而构造字节流时也不会从一个单字节数据类型的值当中产生2个或以上的字节(既然是单字节数据类型,构造字节流时当然只可能产生1个字节)。

但是,如果计算机处理的数据是逻辑意义上的多字节数据类型(int、short、long等),虽然由于构成它们的2个或2个以上的字节是作为一个整体来进行处理的(比如以汇编语言中的数据类型word或dword为单位进行一次性处理,而不是以byte为单位分次处理;更深入地来讲,CPU一般是以字为一个整体来处理数据的,当单个数据不足一个字长时,则将多个数据“拼成”一个字再进行处理),但问题是从计算机物理意义上来说,如前所述,字节才是CPU对内存寻址的最小单位以及存储和传输的最小单元。

因此,CPU在读取作为一个整体来进行处理的多字节数据类型的数据时,必须根据前后2个或2个以上的字节来解析出一个多字节数据类型的值;而且构造字节序列时也会从一个多字节数据类型的值当中产生2个或2个以上的字节。

7.

这样一来,多字节数据类型的数据内部各字节间的排列顺序,是会影响从字节序列恢复到数值的;反之,也会影响从数值到字节序列的构造。

所以,在存储和读取多字节数据类型的数据时,必须按照计算机系统所规定的字节序来进行(这一点程序员了解即可,计算机会自动处理);而尤其是在跨字节序不同的异构计算机系统进行通讯并交换数据时,通讯的任何一方更是必须明确对方所采用的字节序,然后双方将各自接收到的数据按各自的字节序对数据进行转换(有时候需要程序员专门编写转换程序),否则通讯将会出错,甚至直接失败。

8.

实际上,int、short、long等数据类型一般是高级编程语言层面的概念,更进一步而言,这其实涉及到了机器硬件层面(即汇编语言)中的数据类型byte字节、word字、dword双字等在硬件中的表达与处理机制(实质上字节序跟CPU寄存器的位数、存放顺序密切相关)。具体可参看附文:《本质啊本质之一:数据类型的本质》、《寄存器与字、字节》。

【附:本质啊本质之一:数据类型的本质

CSDN博客 博主:band_of_brothers 发表于:2007-10-10 22:20

研究一个层面的问题,往往要从更深的层面找寻答案。这就如C语言与汇编、汇编与机器指令,然而终究要有个底限,这个底限以能使我们心安理得为准,就好比公理之于数学、三大定律之于宏观物理。

在这里就将机器指令作为最后的底限吧,尽管再深入下去还有微指令,但那毕竟是太机器了,可以了。以下所有从C代码编译生成汇编代码用的是命令:cl xxx..c /Fa /Ze。

类型的本质

类型这个概念,好多地方都有讲,但说实话,你真的理解吗?什么是类型?类型是一个抽象的概念还是一个真实的存在?嗯?

开始:

1)“好多相同或相似事物的综合”(辞海)。

2)X86机器的数据类型有byte、word、dword、fword、tword、qword,等等。

3)“给内存块一个明确的名字,就象邮件上的收件人一样。给其一个明确的数据类型,就好象说,邮件是一封信,还是一个包裹。”

4)类型就是一次可以操作的块的大小,就是一个单位,就像克、千克、吨一样。双字,一次操作32位;字,一次操作16位;如果没有各种类型,机器只有一个类型单位——字节,那么当需要一个4字节大小的块时,就需要4次操作,而如果有双字这个类型单位,那么只需要一次操作就可以了。

5)类型,是机器层面支持的,不是软的,是硬的,有实实在在的机器码为证。

类型的反汇编

 

W32dasm反汇编出来的东西,可以看出不同的类型,机器码不同,说明类型是机器硬件级别支持的,不是通过软件实现的,更不是一个抽象的概念。

Opcodes上关于mov的机器码讲的更清楚:

 

需要说明的是,一些大的类型单位,如qword等,在mov等标准指令里是没有的,在一些特殊指令里才能用到,如浮点指令:fmul qword ptr [0067FB08] 机器码:DC0D08FB6700。】

【附:寄存器与字节、字、双字

字节:记为byte,一个字节由8个比特(bit)组成,可以直接存在一个8位寄存器里

   1 0 1 0 1 0 0 1

     一个字节

字:记为word,一个字由2个字节(共16比特)组成,可以直接存在一个16位寄存器里

   1 0 1 0 1 0 0 1  1 0 1 0 1 0 0 1

     高位字节      低位字节

双字:记为dword,一个双字由4个字节(共32比特)组成,可以直接存在一个32位寄存器里

   1 0 1 0 1 0 0 1  1 0 1 0 1 0 0 1  1 0 1 0 1 0 0 1  1 0 1 0 1 0 0 1

     高位字节      次高位字节     次低位字节     低位字节

一个8位寄存器用2位十六进制数表示,只能存1个字节(1个byte类型的数据)

一个16位寄存器用4位十六进制数表示,可存1个字(1个word类型的数据)或2个字节(2个byte类型的数据)

一个32位寄存器用8位十六进制数表示,可存2个字(1个dword类型的数据或2个word类型的数据)或4个字节(4个byte类型的数据)】

(笨笨阿林原创文章,转载请注明出处)

9.

下面简要介绍一下字节序的三种类型:

a) 小端序Little-Endian(低尾端序)

就是低位字节(即小端字节、尾端字节)存放在内存的低地址,而高位字节(即大端字节、头端字节)存放在内存的高地址。

这是最符合人的直觉思维的字节序(但却不符合人的读写习惯),因为从人的第一观感来说,低位字节的值小,对应放在内存地址也小的地方,也即内存中的低位地址;反之,高位字节的值大,对应放在内存地址大的地方,也即内存中的高位地址。

 

b) 大端序Big-Endian(高尾端序)

就是高位字节(即大端字节、头端字节)存放在内存的低地址,低位字节(即小端字节、尾端字节)存放在内存的高地址。

这是最符合人平时的读写习惯的字节序(但却不符合人的直觉思维),因为不用像在Little-EndIan中还需考虑字节的高位、低位与内存的高地址、低地址的对应关系,只需把数值按照人通常的书写习惯,从高位到低位的顺序直接在内存中从左到右或从上到下(下图中就是从上到下)按照由低到高的内存地址,一个字节一个字节地填充进去。

 

c) 中间序Middle-Endian(混合序Mixed-Endian)

混合序具有更复杂的顺序。以PDP-11为例,32位的0x0A0B0C0D被存储为:

 

混合序较少见,常见的多为大端序和小端序。

(注:其实还一种网络字节序(network byte order网络字节顺序、网络序),这里不做深入介绍。)

10.

Intel和AMD的X86平台,以及DEC(Digital Equipment Corporation数字设备公司,后与Compaq合并,之后Compaq又与HP合并)采用的是Little-Endian,而像IBM、Sun的SPARC采用的就是Big-Endian,有的嵌入式平台是Big-Endian的,JAVA字节序也是Big-Endian的。

当然,这不代表所有情况。有的CPU既能工作于小端序,又能工作于大端序,比如ARM、Alpha、摩托罗拉的Power PC、SPARC V9、MIPS、PA-RISC和IA64等体系结构(具体情形可参考处理器手册),其字节序是可切换的,这种可切换的特性可以提高效率或者简化网络设备和软件的逻辑。

这种可切换的字节序被称为Bi-Endian(前缀“Bi-”表示“双边的、二重的、两个的”),用于硬件上指的是计算机存储时具有可以使用两种不同字节序中任意一种的能力。具体这类CPU是大端序还是小端序,和具体设置有关。如Power PC可支持Little-Endian字节序,但其默认配置为Big-Endian字节序。

11.

一般来说,大部分用户的操作系统,如Windows、FreeBSD、Linux是Little-Endian的;少部分,如Mac OS是Big-Endian的。

具体参见下表:

 

12.

所以说,Little Endian还是Big Endian与操作系统和CPU类型都有关系(可能体现在一个处理器的寄存器、指令集、系统总线等各个层次中)。因此在一个计算机系统中,有可能同时存在大端序和小端序两种字节序的现象。

这一现象为系统的软硬件设计带来了不小的麻烦,这要求系统设计工程师必须深入理解大端序和小端序的差别。

其实,很多技术人员在实际的非跨平台桌面应用开发过程中都很少会直接和字节序打交道,但在跨平台及网络应用开发过程中因为涉及到异构计算机系统间的通讯交流,字节序是很难回避的问题。

(笨笨阿林原创文章,转载请注明出处)

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/437443.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python人工智能_人工智能人才缺口千万!学Python抓住风口机会

前不久教育界的一个消息,引发了广泛的关注。今年9月,浙江三到九年级信息技术课将替换新教材,八年级将新增Python课程内容。新高一信息技术编程语言由VB替换为Python,大数据、人工智能、程序设计与算法按照教材规划五六年级开始接触…

【转】刨根究底字符编码之十——Unicode字符集的字符编码方式

一、字符编码方式CEF的选择 1. 由于Unicode字符集非常大(并且作为开放字符集还在不断扩展之中),有些字符的编号(即码点值)需要两个或两个以上字节来表示,而要对这样的编号进行编码,也必须使用两个或两个以上字节。 比如,汉字“…

【转】刨根究底字符编码之十一——UTF-8编码方式与字节序标记BOM

一、UTF-8编码方式 1. 接下来将分别介绍Unicode字符集的三种编码方式:UTF-8、UTF-16、UTF-32。这里先介绍应用最为广泛的UTF-8。 为满足基于ASCII、面向字节的字符处理的需要,Unicode标准中定义了UTF-8编码方式。UTF-8应该是目前应用最广泛的一种Unic…

流水灯verilog实验原理_IC设计实例解析之“流水线技术”

源自:微信公众号 “数字芯片实验室”在IC设计中,如果寄存器之间的组合逻辑延时过大,可能会称为设计中的关键路径,从而降低整个电路的工作频率。如下图所示,是一个输入和输出寄存的算术计算逻辑。在set_input_delay和se…

【转】刨根究底字符编码之十二——UTF-8究竟是怎么编码的

UTF-8究竟是怎么编码的 1. UTF-8编码是Unicode字符集的一种字符编码方式(CEF),其特点是使用变长字节数(即变长码元序列或称变宽码元序列)来编码。目前一般是1到4个字节,当然,也可以更长。 为什么要变长呢?这可以理解为按需分配…

iphone闪退修复工具_升级 iOS 14.2 微信闪退?iPhone 12 维修贵

原标题:升级 iOS 14.2 微信闪退?iPhone 12 维修贵昨天,苹果推出 iOS 14.2 正式版系统,我相信你们都知道了,主要新增几点功能,并没有针对性解决耗电问题,而对 AirPods Pro 充电进行优化&#xff…

【转】刨根究底字符编码之十三——UTF-16编码方式

1. UTF-16编码方式源于UCS-2(Universal Character Set coded in 2 octets、2-byte Universal Character Set)。而UCS-2,是早期遗留下来的历史产物。 UCS-2将字符编号直接映射为字符编码(CEF,而非CES,详见前文中对现代字符编码模型的解释)&a…

java xml 默认名称空间 xpath_创意产业园办公空间设计

你说想要的样子永远不是现在你的样子,桃花源或许永远在每个人的心底。桃花源办公空间整体外观入口前厅及走廊空间天花板细节桃花源其实是我们每个人或者一群人的乌托邦,一座苏联式的厂房是心中桃花源的开端,光、空、间、穿、行、高、纵、新、…

【转】刨根究底字符编码之十四——UTF-16究竟是怎么编码的

1. 首先要注意的是,代理Surrogate是专属于UTF-16编码方式的一种机制,UTF-8和UTF-32是不用代理的。 如前文所述,为了让UTF-16能继续编码基本平面后面的增补平面中的码点值,于是扩展了UTF-16编码方式。 具体的扩展方法就是为其增…

java环境_配置java环境变量

1.找到此电脑我的电脑右键属性。2.点击高级系统设置。3.点击环境变量。4.点击新建。5.创建变量名JAVA_HOME必须是大写,变量值找到你的jdk的根目录复制下来,然后粘贴进去,点击确定。6.再次点击新建7.创建变量名为path、变量值,找到…

idea+JRebel实现项目热部署

今天发现这个插件,简直神了,太爽了,每次改完代码重启都要等半天,回不去了 第一步:安装插件 第二步:在线生成GUID 网址:在线GUID地址 第三步:打开jrebel 如下所示面板,选…

【转】刨根究底字符编码之十五——UTF-32编码方式

1. UTF-32在UTF目前常用的三种编码方式(UTF-8、UTF-16、UTF-32)中,是最为简单的一种编码方式。UTF-32编码方式不使用任何编码算法将Unicode字符码点值(即编号字符集CCS中的字符编号)转换为码元序列,而是将每个Unicode字符码点值直接表示为一个32位的码元…

小米手机证书信任设置在哪里_小米手机闹钟在哪里?闹钟怎么设置?怎么找到闹钟?...

随着智能手机的大量普及,人们会发现手机里的功能越来越多,绝不像以前那样只能打打电话发发短信那么简单了。而这些功能当中很多我们常用的功能有的人却不会用、不会设置,甚至根本找不到在哪里?比如说手机闹钟这个功能,…

【转】刨根究底字符编码之十六——Windows记事本的诡异怪事:微软为什么跟联通有仇?

1. 当用一个软件(比如Windows记事本或Notepad)打开一个文本文件时,它要做的第一件事是确定这个文本文件究竟是使用哪种编码方式保存的,以便于该软件对其正确解码,否则将显示为乱码。 一般软件确定文本文件编码方式的方法有如下三种&#xf…

win10切换输入法快捷键_输入法失灵怎么办?该怎么恢复?

我们都尝试过在使用win10的时候,输入法无法切换,只能打英文不能输入汉字,对于要打字、打游戏来说都是非常麻烦的。所以,当输入法有问题的时候,应该要怎么样修复?主编:渣渣辉,是兄弟就…

【转】刨根究底字符编码【2.0版】(1):开篇

首先跟大家分享一个有趣的亲身经历。有一次,在网上我看到有程序员发了一个帖子,帖子题目乍一看让人感到惊愕,但细一想又让我会心一笑。 这个帖子的题目大致上是这样的:字符编码是不是让程序员最感到恶心的问题? 更有…

数位dp模板 最高位最低位_无纸化办公入门指南(数位板篇)

居家办公的这段时间,你们有没有遇到无纸化办公的问题?作为一名编辑,在我社规定不能寄纸稿的情况下,看电子稿成了常态。如果是word版尚且可以批注,不影响工作效率。但如果是PDF呢?怎样保证改稿的效率&#x…

AQS

1 AQS抽象的队列同步器,AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,如常用的ReentrantLock/Semaphore/CountDownLatch 首先AQS维护了一个volatile 修饰的state和一个FIFO的同步队列(多线程争用资源被…

屏幕录像专家6.0_迅捷屏幕录像工具和屏幕录像专家哪个更好用?

随着社会的发展,屏幕录像常常都需要使用,然而有些新手朋友就想知道,到底是电脑中自带的屏幕录像专家好用,还是迅捷屏幕录像工具好用,这两者都是当前使用率比较高的软件,今天小编就为大家分析分析&#xff0…