一文带你了解编码集

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一文带你了解编码集相关的知识,希望对你有一定的参考价值。

编码集1 ASCII编码:127个字母 8个数据位足够存储字母、数字、符号,最大支持到0x7F。2 GB2312编码每个汉字占据2个字节(高位和低位),

参考技术A

编码集

1. ASCII编码:

127个字母 8个数据位足够存储字母、数字、符号,最大支持到0x7F。

2. GB2312编码  

每个汉字占据2个字节(高位和低位),16个数据。GB2312是对ASCII的中文扩展,共包含7000多个汉字。是计算机发展到中国后发展起来的编码,检测高位和低位,如果同时大于0x7F,则认为是GB2312,否则认为是ASCII编码。

相关推荐:《Python视频教程》

3. GBK(1995)和GB18030(2005/2000)

每个汉字占据2个字节,由于汉字的数量太大,GB2312不能满足需求。GBK包括了GB2312的所有内容,

同时增加了近20000个新的汉字(包括繁体)和符号 。只要求高位大于0x7F,低位可以小于0x7F,认为是中文。 

>  国家标准GB18030-2000《信息交换用汉字编码字符集基本集的补充》是我国继GB2312-1980和

GB13000-1993之后最重要的汉字编码标准,包含多种我国少数民族文字,其中收入汉字70000余个。

4.Unicode编码 

> 定长存储, 将所有语言都统一到一套编码集,通常使用2个字节,有的是4个字节。收录很全。

分为17个面,基本面采用2个字节,普通中文子也在基本面中,另外16个面是4个字节。

不兼容ASCII码,即存储的时候,对ASCII码前面补0,导致存储的数据变大。

5. utf-8---变长存储

> 国际标准组织(ISO)制定英文字符使用1个字节,沿用原来的ASCII码。

> 使用1~4个字节表示一个符号,中文存储使用3个字节(ascii码中的内容用1个字节保存欧洲的字符用2个字节保存东亚的字符用3个字节保存特殊符号用4个字节)

> Unicode是内存编码表示方案(规范),而utf-8是如何保存和传输Unicode的方案(实现)

> 优点:虽然内存汇总的数据都是Unicode,但当数据保存到磁盘或者用于网络传输时,使用utf-8会节省更多的流量和硬盘空间。

如何判断几个字节表示一个字符:

每个字节添加识别位,其中高位识别位为4位,低位识别位为2位。判断高位字节开头有几个1,可以确定共有几个字节来表示一个字符。

6. utf-8和Unicode对应关系

utf-8去掉识别位,变成unicode。

一文带你深入了解《C语言对齐与非对齐访问》(ARM指令集)

首先你需要知道在什么情况下你才需要用到对齐与非对齐这个概念

typedef struct 
	char* pCmd;				//4个字节												
	char *pCmdPara;         //4个字节           					
	char isFree;			//4个字节												  
AT_QUEUE_ITEM_T;

AT_QUEUE_ITEM_T q[500] = 0; //12*500 = 6000个字节

上面的代码 isFree 会应为对齐的原因填充成4个字节。所以原本只有9*500=4500个字节的数据,在这里硬生生变成了6000个字节,浪费了1500个字节。这对资源本就有限的单片机来说是致命的。

有没有解决方案呢?答案当然是有的。

#pragma pack(1)  //强制一字节对齐
typedef struct 
	char* pCmd;				//4个字节												
	char *pCmdPara;         //4个字节           					
	char isFree;			//1个字节												  
AT_QUEUE_ITEM_T;
#pragma pack()

AT_QUEUE_ITEM_T q[500] = 0; //9*500 = 4500个字节

这里我们使用 #pragma pack(n) 的预编译指令,将结构体强制1字节对齐。

如果用该结构声明的变量要作为参数传递入函数内部怎么办?

IAR 提供了 __packed属性

#pragma pack(1)  //强制一字节对齐
typedef struct 
	char* pCmd;				//4个字节												
	char *pCmdPara;         //4个字节           					
	char isFree;			//1个字节												  
AT_QUEUE_ITEM_T;
#pragma pack()

AT_QUEUE_ITEM_T q[500] = 0; //9*500 = 4500个字节

void test(AT_QUEUE_ITEM_T __packed par )


(备注:关于#pragma pack() 这个预编译指令的详细解释可以看这篇文章。 很多人不了解的嵌入式C高级用法_boazheng的博客-CSDN博客

你以为到这里就完了?

就这??

NO!NO!NO!

图样图森破!

首先并不是所有硬件平台都支持非对齐访问,且并不是所有操作都支持非对齐。

所以你首先的知道

什么是数据的对齐和非对齐

下面我们来看一下Cortex-M3与Cortex-M4权威指南 6.6的内容

 

 划重点:

ARM7/9/10只允许对齐传输,Cortex-M3和4 支持非对齐传输,非对齐传输不能在多加载/存储指令,栈操作指令,排他访问指令,位段操作中使用,且非对齐访问会降低性能。

文中没有对加载/存储指令给出明确说明,哪....

什么是加载/存储指令

存储指令用于在寄存器和存储器之间传送数据,加载指令用于将存储器中的数据传送到寄存器,存储指令则完成相反的操作。常用的加载存储指令如下:

那么在Cortex-M3与Cortex-M4权威指南中提到的多加载是什么鬼?

在上表中所有数据类型的是32的都不支持,多载因该就是LDM,LDRD这2个了,存储就是STR,STM,STRD,PUSH。

而STRB,LDRH正是这几个指令的存在才允许你非对齐访问。

我们知道了什么是加载,存储的指令,哪。。。。

什么是排他访问

Cortex-M3与Cortex-M4权威指南中是这样描述的。

 说人话就是。。。

我们知道临界区使任务有秩序地访问共享资源,避免资源竞争。但全局中断屏蔽不仅需要许多额外的指令周期,而且降低了紧急中断的响应速度。的排他访问旨在改善这一问题。

ARMv7指令集包含三对同步原语 ( synchronization primitives ) 。这三对同步原语分别为:

32位数据读写的 LDREX 和 STREX,
16位数据读写的 LDREXH 和 STREXH,
8位数据读写的 LDREXB 和 STREXB,
此外,还有用于清零排他访问标识的 CLREX 

这些同步原语给多任务提供了一种不阻塞的资源竞争应对方法 —— 排他访问。排他访问实现有保障的 “ 读 - 改 - 写 ” 操作,可以用于信号量、自旋锁等系统服务。

请看图。。。。

 所以我们可以看出排他访问主要用在有嵌入式系统的情况下,信号量,自旋锁,互斥锁等等的应用上。

本文精华所在:

罗里吧嗦的说了这么多干巴巴的感念,到底有什么用?

那就是非对其访问什么时候用,怎么用?什么时候不能用。

1.在IAR中所支持的硬件平台

 这里我们只关注ARM部分。在ARM中在Cortex-M3与Cortex-M4都是支持非对其访问的,但Cortex-M0不支持。

2.在什么样的情况下不要用。

使用__packed#pragma pack 有一个显著的缺点#pragma pack是每次访问结构中未对齐的元素都会使用更多的代码,也就是说在在需要高性能的地方最好不要用,如果一定要用,请自己平衡高性能和存储空间之间的矛盾。

其次函数内部直接使用非对其访问会影响出栈入栈,所以可以将非对齐访问的内容放在堆里,比如用Malloc或者静态变量来申明他的实体。

还有,不要对信号量类型的变量使用__packed属性修饰符。

3.什么时候用

例如本文一开始说的可以节省大量空间的地方,还有我们在解析或封装通信字节流的时候,或者需要写入Flash的结构等。。总的来说就是用在需要节约空间的地方。

相关资料阅读:

IAR关于未对其访问的介绍

Accessing Unaligned Data | IAR Systems

微软关于#pragma pack的介绍

pack pragma | Microsoft Learn

扩展阅读:

关于C语言怎么分配内存的资料

 【C】从内存出发理解C语言变量作用域与生命周期_NjustMEMS_ZJ的博客-CSDN博客

以上是关于一文带你了解编码集的主要内容,如果未能解决你的问题,请参考以下文章

一文带你深入了解《C语言对齐与非对齐访问》(ARM指令集)

一文带你深入了解《C语言对齐与非对齐访问》(ARM指令集)

一文带你了解 Vim 的起源

一文带你了解Java8之Stream

一文带你了解Java8之Stream

一文带你了解Java8之Stream