现代 C++ 编程实战
吴咏炜
前 Intel 资深软件架构师
34196 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 51 讲
加餐 (1讲)
现代 C++ 编程实战
15
15
1.0x
00:00/00:00
登录|注册

11 | Unicode:进入多文字支持的世界

codecvt: Deprecated in C++ due to security and usability issues
ICU4C: Unicode support library
iconv: Encoding conversion interface
Windows API: MultiByteToWideChar, WideCharToMultiByte
Windows: UTF-16 usage
Unix: UTF-8 usage
Unicode escape sequences
New UTF-8, UTF-16, and UTF-32 string literals
String types: string, wstring, u16string, u32string, u8string
char, wchar_t, char16_t, char32_t
Byte Order Mark (BOM) for encoding differentiation
Common encoding methods: UTF-32, UTF-16, UTF-8
Encoding points from 0x0 to 0x10FFFF
Characters are distinguished by meaning, not by form
Supports over 137,994 characters
Later expanded to include various special characters
Initially aimed at active modern characters
Unified encoding effort
GBK
EUC-CN
GB2312
Mostly compatible with ASCII
ISO 646 series, ISO/IEC 8859 series
Includes control characters, numbers, Latin letters, spaces, and basic punctuation
Represents most common characters
7-bit encoding
cppreference.com, "std::codecvt"
Alisdair Meredith, "Deprecating "
cppreference.com, "Standard library header "
ICU Technical Committee, ICU—International Components for Unicode
Wikipedia, "iconv"
Microsoft, "WideCharToMultiByte function"
Microsoft, "MultiByteToWideChar function"
Wikipedia, "Byte order mark"
Wikipedia, "UTF-8"
Wikipedia, "UTF-16"
Wikipedia, "UTF-32"
Wikipedia, "Unicode"
Wikipedia, "GBK"
Wikipedia, "EUC-CN"
Wikipedia, "GB 2312"
Wikipedia, "EBCDIC"
Wikipedia, "ASCII"
UTF-8 is more space-efficient compared to other UTF encodings
UTF-32 may not be simple in cases where memory efficiency is crucial
UTF-32 simplifies handling due to direct mapping of encoding points
Programming support
Platform differences
C++ support
Unicode
Chinese character sets
Other encoding systems
ASCII
Reference
Conclusion
Unicode
Unicode and C++ Support

该思维导图由 AI 生成,仅供参考

你好,我是吴咏炜。
这一讲我们来讲一个新话题,Unicode。我们会从编码的历史谈起,讨论编程中对中文和多语言的支持,然后重点看一下 C++ 中应该如何处理这些问题。

一些历史

ASCII [1] 是一种创立于 1963 年的 7 位编码,用 0 到 127 之间的数值来代表最常用的字符,包含了控制字符(很多在今天已不再使用)、数字、大小写拉丁字母、空格和基本标点。它在编码上具有简单性,字母和数字的编码位置非常容易记忆(相比之下,设计 EBCDIC [2] 的人感觉是脑子进了水,哦不,进了穿孔卡片了;难怪它和 IBM 的那些过时老古董一起已经几乎被人遗忘)。时至今日,ASCII 可以看作是字符编码的基础,主要的编码方式都保持着与 ASCII 的兼容性。
ASCII 里只有基本的拉丁字母,它既没有带变音符的拉丁字母(如 é 和 ä ),也不支持像希腊字母(如 α、β、γ)、西里尔字母(如 Пушкин)这样的其他欧洲文字(也难怪,毕竟它是 American Standard Code for Information Interchange)。很多其他编码方式纷纷应运而生,包括 ISO 646 系列、ISO/IEC 8859 系列等等;大部分编码方式都是头 128 个字符与 ASCII 兼容,后 128 个字符是自己的扩展,总共最多是 256 个字符。每次只有一套方式可以生效,称之为一个代码页(code page)。这种做法,只能适用于文字相近、且字符数不多的国家。比如,下图表示了 ISO-8859-1(也称作 Latin-1)和后面的 Windows 扩展代码页 1252(下图中绿框部分为 Windows 的扩展),就只能适用于西欧国家。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了字符编码的发展历程,重点介绍了ASCII、GB2312、GBK和Unicode等编码方式的演变。ASCII只能表示有限的字符,而GB2312和GBK虽然支持中文,但无法满足多语言需求。为解决多语言字符编码问题,Unicode采用UTF-8编码方式,与ASCII兼容,统一了不同语言字符的编码点,大大扩展了字符范围。Unicode已包含了137,994个字符,覆盖了各种语言和特殊符号,提供了UTF-32、UTF-16和UTF-8等多种编码方式。文章还介绍了C++中的Unicode字符类型,包括`char16_t`、`char32_t`和`char8_t`等,以及新的字符串字面量表示方式。此外,文章还探讨了不同平台对Unicode编码的处理方式。在Unix系统中,全面转向了UTF-8,而在Windows系统中,由于历史原因和向后兼容性的需要,一直使用`char`表示传统编码,使用`wchar_t`表示UTF-16。文章还介绍了在不同平台下处理字符串的方式,以及编程支持方面的内容。总之,Unicode作为一种统一的多语言字符编码方式,为跨语言交流和软件开发提供了便利,是当前字符编码领域的重要进展。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《现代 C++ 编程实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(22)

  • 最新
  • 精选
  • c1rew
    http://c1rew.github.io/2017/03/02/字符集和字符编码/ 很早之前写的一篇文章,供大家参考

    作者回复: 既然你贴在这里,我就指出一下文中的一些小问题吧。 - 时间线不对。GB18030(甚至 GBK)是在 Unicode 之后出现的。GB18030 的四字节编码是基于 Unicode 的。 - 有一处 UCS 写成了 USC。 - “目前的用于实用的 Unicode 版本对应于 UCS-2,即使用16位来表示一个Unicode字符”:对于 2017 年的文章,这么写是不合适的。不说很多汉字在 BMP 之外,表情字符大家总要用的吧? - UCS-4 虽然最初被定义为 31 位,但从 2003 年开始就被规定为范围是从 0 到 0x10FFFF 了。换句话说,只用 21 位。 - UTF-16 和 UCS-2 是不同的。UTF-16 有 16 位和 32 位两种情况,而 UCS-2 只有 16位一种。 - 虽然 U+FEFF 在文件中间出现应当被当作 zero width no-break space,但在文件开头,它只被叫做 BOM。此外,zero width no-break space 这一用法从 Unicode 3.2 开始就被反对使用(deprecate)了。目前,U+FEFF 就只有 BOM 一种意思。 可能像是挑刺,抱歉了。但我不希望别人对这些事实有错误的理解。

    2020-02-14
    4
    38
  • 皮皮侠
    问个题外问题,Qt里中文的处理总是有问题,老师怎么看,有什么终极解决办法呢?

    作者回复: Qt 不熟。不过,也就不外乎这几种情况了。搞清楚源代码的编码、字符串的内码、输入输出要求的编码,作合适的转换,应当可以解决。 不要忘了在 Windows 上编译 UTF-8 源码的文件,一定要有 BOM 字符。这也是很多错误的来源。网上搜 Qt 的编码问题,似乎很多问题就是跟源代码的编码相关的。

    2020-02-27
    5
    4
  • 勿更改任何信息
    由于 Unicode 不使用 U+FFFE --> 应该是不使用 U+FEFF 吧

    作者回复: 一个简单的搜索就能发现我是对的,你是错的。 提问题前自己不先搜索一下,是不会提问的表现。

    2023-04-08归属地:福建
    2
    1
  • Milittle
    1. 有一个问题想问下老师,传统编码是不是相对于UTF编码之外的那些编码方式。 2. 再就是对于我们编程中使用的不同编码方式的字面量来说,最后生成的字节数对应是不同的么?是这个意思么? 3. 还有就是u8string u16string u32string 默认是一个元素所占的字节数分辨是 1 2 4么? 4. 老师文章中提出一个UTF-16在0XD800-0XDFFF之间没有用作unicode code point。这是历史原因决定么 然后就是怎么可以找到unicode code point所对应的文字关系表? 从UTF-32转UTF-8和UTF-16老师给出例子,这个可以当作一个算法来记忆。 5. 就是操作系统的编码方式是最终决定你的字符串显示在终端的样子么?我举一个例子,加入你程序中一个字符串是UTF-8,但是你的操作系统使用的是GBK,那么显示出来的样子应该会乱码吧? 我的理解也就是程序什么编码方式,操作系统也应该是什么编码方式,才能输出正确的文字? 以上问题有些可能是我没有理解对 王老师给予指导 谢谢~

    作者回复: 1. “传统编码”在Windows上有特别含义。对于简体中文Windows,就是GBK编码了。 2. 不同的编码方式,字面量的值会不同,这是最重要的。字节数可能一样,可能不一样。比如繁体中文的汉字,在GBK里和在Big5里就不同。编码不正确,字符可能出不来,比如简体中文在Big5里就都没有。 3. 是,每个元素分别是8、16、32比特。 4. 0XD800-0XDFFF正好没有用吧,然后就用于UTF-16的扩展了。转换算法我描述得不算太详细,因为这个资料真的是很多的。 完整的Unicode文字表网上也可以找到,如: https://unicode.org/charts/ https://unicode-table.com/ 5. 编码是可以转换的。如果不加转换输出就会乱码。 从操作系统来说,Windows内部使用UTF-16,但如果代码中使用char/string,Windows接口一般当成“传统编码”来转换处理。Unix系统里一般全面使用UTF-8。

    2020-02-26
    1
  • 天天
    1. utf32字节数固定支持随机访问字符,其他2个则需要遍历前面的字节,经过计算才能解出第N个字符 3. 要看具体存储的是啥字符, 英文utf8省空间, 中文utf16

    作者回复: OK,1、3 的回答都没什么问题。👍

    2020-02-05
    1
  • 三味
    这两天写玩具代码, 环境就是win10, vs2017, 写控制台. 我源代码是utf8无bom格式. 什么都好, 就是用fgets获取输入, 无法获取中文字符串... 折腾好久... 最后还是都改成了ansi... ansi这个诡异的名字确实值得吐槽啊...明明就是GBK... 字符编码真是太麻烦了...

    作者回复: ANSI 是指 Windows 的传统系统编码。源代码中如果含中文,必须用 UTF-8 + BOM 保存(专栏中说过的)。

    2019-12-20
    1
  • Geek_0705cc
    大头在前、小头在前是什么意思呢?不如这样说的清楚。大端模式指的是:高位字节存储在内存的低地址处;

    作者回复: 大小头(端)不是我要说明的重点,因此我只是用例子来说明。 另外,你的表述方式是有问题的,因为文件没有高地址和低地址。

    2023-01-25归属地:河南
  • chang
    文中“由于 Unicode 不使用 U+FFFE,在文件开头加一个 BOM 即可区分各种不同编码:”,应该是U+FEFF吧

    作者回复: 没写错,是“不使用” U+FFFE。再读一遍。

    2021-06-03
    2
  • 蓦然回首
    上面这几种之间相互有影响吗?到底之间关系是如何?平时我们开发过程中,应该怎么理解这几者之间的关系?感觉这方面一直没弄清楚

    作者回复: 参见前面的回答。 互相基本没影响。但是,如果你要把程序里硬编码的字符串跟输入一起混合输出,那就必须保证编码相同了。如果输出到终端,那还要保证终端的设置与之相匹配——Linux上通常为UTF-8,(中文)Windows上通常为GBK。

    2021-01-27
  • 蓦然回首
    老师,请教个问题,我们平时开发,好像编码有几种方面的编码问题: 1.源码文件本身的编码,IDE或者编辑器设置的编码等 2.程序运行时刻当中程序本身的编码, 3.程序运行过程中所打开文件的编码 4.接收或者发送网络数据的不同编码 在编码方面一直这方面有些困惑,希望能解答一下!

    作者回复: 1. 源代码的编码通常影响不大,主要影响是字符串的编码结果。 2. 基本上没有程序本身编码的概念。但是,运行时有缺省编码的概念,影响对输入输出的解释。 3、4. 通常由程序自行解释,除非你使用了运行时库提供的到宽字符的转换函数。

    2021-01-27
    4
收起评论
显示
设置
留言
22
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部