一文带你了解编码集
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的介绍
扩展阅读:
关于C语言怎么分配内存的资料
【C】从内存出发理解C语言变量作用域与生命周期_NjustMEMS_ZJ的博客-CSDN博客
以上是关于一文带你了解编码集的主要内容,如果未能解决你的问题,请参考以下文章