c语言基础--使用不同编码字符--字符集--ANSI ascii gbk gb2312 gb18030 unicode utf8 big5 wchar_t 处理器大小端

【首先简单理解几种编码】

ascii是ansi标准,包含128个字符(7 bits)
我们说的ansi编码,通常特指windows平台的一种ascii扩展码,他将ascii码扩展到8bits,增加了0x80-0xff共128个字符。在cjk(chinese japanese korean)系统中,ansi还常常指代包括多字节内码的编码。不难看出,所谓ansi编码,就是一种未经国际标准化(也没办法标准化,因为扩展部分的内码存在交集)的兼容ascii编码的,非unicode字符集编码

GB 2312 或 GB 2312-80 最早中国字符编码集,就是GB国标,中国国家标准简体中文字符集,约6763 个汉字,其中一级汉字 3755 个,二级汉字 3008

GBK 即汉字内码扩展规范,就是GBK国标扩,兼容GB 2312,约 21886 个汉字和图形符号,【包含BIG5 中的全部汉字】

BIG5 台湾、香港地区的一个繁体字编码方案

GB 18030,最终汉字编码,与GB 2312-1980 和 GBK 兼容,共收录汉字70244个
【搞清GB 18030,GBK,GB 2312总体关系,都是【双字节】】

Unicode,统一码,包括世界上所有字符【双字节】,【与上面的汉字编码不兼容,不一致】

utf8是Unicode的具体一种实现方式,【变长编码】【一个汉字占3字节,字母占一个字节】,utf8的编码就是Unicode的编码,不过会变长处理后存储

【程序对字符编码的解释】
字符就是一串 unsigned char[] 数组,每一个char,表示一个字节,数字0-255

程序对字符编码的解释就是如何看待这一串unsigned char[] 数组表示的数字序列。编码只是规定数字序列表示的字符含义,程序看到的也只是具体的数字序列,

汉字不同编码:我     []内为16进制编码
GB2312编码:[CED2]  BIG5编码:[A7DA]  GBK编码:[CED2]   GB18030编码:[CED2]   Unicode编码:[6211] utf8编码:[6211] utf8实际存储格式[e68891]

中国windows的cmd默认使用gbk,代码页936

//printf输出汉字
//需要vs,文件--高级保存选项--编码,代码页936,保证 aa是gbk编码
#include <stdio.h>

int main()
{
    unsigned char aa[] = "我";
    unsigned char bb[] = {0xce,0xd2,'\0'};
    //查看编码
    for (int i = 0; i < strlen(aa); i++)
    {
        printf("%x\n", aa[i]);
    }
    printf("%s\n", bb);
    return 0;
}

cmd切换代码页

chcp 65001  就是换成UTF-8代码页    

chcp 936 可以换回默认的GBK    

chcp 437 是美国英语

显示utf8汉字

////printf输出汉字
//需要vs,文件--高级保存选项--编码,代码页936,保证 aa是gbk编码
#include <stdio.h>

int main()
{ 
    unsigned char aa[] = "我";
    unsigned char bb[] = {0xe6,0x88,0x91,'\0'};
    //打印的还是gbk编码
    for (int i = 0; i < strlen(aa); i++)
    {
        printf("%x\n", aa[i]);
    }
    //输出utf8字符
    printf("%s\n", bb);
    return 0;
}

ctrl+f5 编译运行,看到gbk编码,和乱码
新开cmd窗口

chcp 65001
把生成的exe拖动cmd后,回车运行,看到utf8编码汉字

最后是unicode与utf8转换方法

Unicode符号范围        | UTF-8编码方式
(十六进制)             | (二进制)
----------------------+---------------------------------------------
      0 <--> 0x7f     | 0xxxxxxx
   0x80 <--> 0x7FF    | 110xxxxx 10xxxxxx
  0x800 <--> 0xFFFF   | 1110xxxx 10xxxxxx 10xxxxxx
0x10000 <--> 0x10FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
汉字“我”,unicode:6211,二进制:0110 0010 0001 0001【一定要补全最前面的0,一共双字节16位】
填充到utf8编码,6211属于0x800 <--> 0xFFFF,所有需要三字节

1110xxxx 10xxxxxx 10xxxxxx (规则)
    0110   001000   010001 (unicode编码,从右向左依次填充x)
--------------------------
11100110 10001000 10010001 (utf8实际存储编码)

处理器大小端对字符编码的影响

0x11223344,机器字长,一个内存地址存储的逻辑值
存储方式:
大端:11|22|33|44
小端:44|33|22|11
    低地址---》高地址
大端主要是与人看的一致
小端主要是与值得逻辑一致(低位在低地址)

intelcpu,是小端格式,wchar_t是双字节char

#include <stdio.h>

int main()
{
    wchar_t *bb[] = {'a','b'};
    //bb2位数字,占4字节
    printf("%d\n", sizeof(*bb));
    只能打印出a
    printf("%s\n", bb);
    return 0;
}

【原因】

机器字长32位,所有小端格式是对32位高低转换
wchar_t 双字节 16wchar_t *bb[] = {'a','b'}  32位
逻辑上内存结构是:00000000 01100001  00000000 01100010 (00 97 00 98 十进制ascii码)
但是小端的存储是:01100001 00000000  01100010 00000000 (97 00 98 00 十进制ascii码)

printf读到的是小端存储的值,所有打印了a,下个字节是0,表示字符串结束

猜你喜欢

转载自blog.csdn.net/c5113620/article/details/79994243
今日推荐