您的位置:首页 > 理论基础

计算机编码原理——不同数据类型存储中文编码

2020-03-09 22:32 489 查看

  作者以前在Windows平台编程时,对于字符串显示中文以及不同的字符集编码格式不太理解。最近编写资料用到这部分知识,便通过自己的分析和参考资料做了简单运用,下面我们一起分析常用的编码集与中文编码!


章节预览:


1.字符数组存储GB2312中文编码
2.GB2312标准
3.输出乱码原理
4.整数存储GB2312中文编码
5.Uncode
6.UTF-8
7.整数存储UTF-8中文编码


章节内容:


字符数组存储GB2312中文编码:


  首先,我们通过字符数组输出“你好”,参考代码:
    unsigned char testch[4] = {0};
    memcpy(testch, “你好”, strlen(“你好”));
    printf("%s|", testch);

    得出的结果为:你好烫烫烫烫
                              |


首先,我们分析testch输出的信息:

  我们定义一个256字节的字符数组保存testch值:
    unsigned char testch2[256] = {0};
    memcpy(testch2, testch, 255);
      展开testch2:
        - testch2 0x00aff9f0 "你好烫烫烫烫
        " unsigned char [256]
        [0] 196 ‘?’ unsigned char
        [1] 227 ‘?’ unsigned char
        [2] 186 ‘?’ unsigned char
        [3] 195 ‘?’ unsigned char
        [4] 204 ‘?’ unsigned char
        [5] 204 ‘?’ unsigned char
        [6] 204 ‘?’ unsigned char
        [7] 204 ‘?’ unsigned char
        [8] 204 ‘?’ unsigned char
        [9] 204 ‘?’ unsigned char
        [10] 204 ‘?’ unsigned char
        [11] 204 ‘?’ unsigned char
        [12] 10 ’
        ’ unsigned char
        [13] 0 unsigned char

        Byte13值为0,程序输出的testch信息到这里终止。


然后,我们分析testch输出的信息内容:

  GB2312规定对匹配的每个字符采用两个字节表示,在VS2010编译器中可以这么认为(与GB2312标准定义有出入):
    当前字节值为0-128时,采用国际Ascll码表方式计算,当前字节信息会以Ascll码表对应符显示;
    当前字节值大于或等于129时,后面的一个字节与当前字节被认为是一个GB2312编码匹配(采用两个字节位数合并成一个16位数字(低字节在低8位,高字节在高8位)),数字值如果在GB2312编码内,将显示GB2312中的对应信息,否则(数字值如果不在GB2312编码内)按照单个字节显示。


GB2312标准:


  GB2312是中国主要官方字符集的注册名称,用于简体中文字符。GB缩写为国家标准,由中国国家标准总局1980年发布,1981年5月1日开始使用。GB2312编码共收录汉字6763个,其中一级汉字3755个,二级汉字3008个。

  GB2312规定对收录的每个字符采用两个字节表示,第一个字节为“高字节”,对应94个区;第二个字节为“低字节”,对应94个位,所以它的区位码范围是:0101-9494。区号和位号分别加上0xA0就是GB2312编码。例如最后一个码位是9494,区号和位号分别转换成十六进制是5E5E,0x5E+0xA0=0xFE,所以该码位的GB2312编码是FEFE。

  GB2312编码范围为0xA1A1—0xFEFE,其中汉字的编码范围为0xB0A1-0xF7FE,第一字节0xB0-0xF7(对应区号:16——87),第二个字节0xA1-0xFE(对应位号:01—94)。


输出乱码原因:


  当我们使用字符数组存储信息并且没有做字符串结尾(最后一个字节置为空字符)时,将会发生“内存访问越位”的情况,因为,VS2010编译器会自动把未使用的栈内存空间按字节全部初始化为0xCC(无符号204),当两个字节都为0xCC时,显示为GB2312编码中的“烫”汉字。


整数存储GB2312中文编码:


unsigned short:

  在32位编译器中,一个unsigned short类型占用2个字节,我们可以通过unsigned short数组保存数据,并输出“你好”:
    unsigned short sho[3] = {58308,50106,0};
    printf("%s", sho);
    第一个值:58308 转成二进制数字为 1110 0011,1100 0100,中文“你”;
    第二个值:50106 转成二进制数字为 1110 0011,1011 1010,中文“好”;
    第三个值:作为空字符使用。

    位数顺序:左高右低。


unsigned int:

  在32位编译器中,一个unsigned int类型占用4个字节,输出“你好”:
    unsigned int sho[2] = {3283805124,0};
    printf("%s", sho);
    第一个值:3283805124 转成二进制数字为 1100 0011 1011 1010,1110 0011 1100 0100‬,中文“你好”;
    第二个值:作为空字符使用。

    使用unsigned int类型存储GB2312数据时,采用2个字节为一组,3、4字节(中文“好”)在左,1、2字节(中文“你”)在右, 组内顺序也是左高右低。


long long:

  在大部分编译器中,一个long long类型占用8个字节,输出“你好呀”:
    long long sho = 208708629619652;
    printf("%s", &sho);
    参数值:208708629619652 或 十六进制 0xBDD1C3BAE3C4 转成二进制数字为:
    1011 1101 1101 0001,1100 0011 1011 1010,1110 0011 1100 0100,中文“你好呀”;

    使用long long类型类型存储GB2312数据时,存储形式与int相同。示例中我们只输出3个GB2312字符,6、7字节为空字符使用。

  在这里我们可以看出使用无符号类型和有符号类型输出的结果相同,大部分示例中采用无符号类型只是为了方便参考数据。


Uncode:


  在非 Unicode 环境下,由于不同国家和地区采用的字符集不一致,很可能出现无法正常显示所有字符的情况。微软公司使用了代码页(Codepage)转换表的技术来过渡性的部分解决这一问题,即通过指定的转换表将非 Unicode 的字符编码转换为同一字符对应的系统内部使用的 Unicode 编码。
MultiByteToWideChar是一种windows API 函数,该函数映射一个字符串到一个宽字符(Unicode)的字符串。


UTF-8:


  UTF-8是针对Unicode的一种可变长度字符编码,它可以用来表示Unicode标准中的任何字符,UTF-8将每个Unicode字符编码为1到4个八位字节的可变数字,其中八位字节的数目取决于分配给Unicode字符的整数值。这是对Unicode文档的有效编码,主要使用US-ASCII字符,因为它将范围在U + 0000到U + 007F之间的每个字符表示为一个八位字节。


整数存储UTF-8中文编码:


long long:

  由于UTF-8字符集存在字节不确定因素,直接使用long long类型输出“你好”:
    system(“chcp 65001”); //在VS2010编译器中,我们选择向控制台输出UTF-8信息
    long long sho = 208520219770340;
    printf("%s", &sho);
    参数值:208520219770340 或十六进制 0xBDA5E5A0BDE4 转成二进制数字为:
‬    1011 1101 1010 0101 1110 0101, 1010 0000 1011 1101 1110 0100‬,中文“你好”;

    示例中“你”、“好”分别占用三个字节,6、5、4字节(中文“好”)在左,3、2、1字节(中文“你”)在右, 组内顺序也是左高右低。

  • 点赞
  • 收藏
  • 分享
  • 文章举报
昱. 博客专家 发布了104 篇原创文章 · 获赞 585 · 访问量 21万+ 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: