Contents

DevC++中文显示乱码问题解决

问题发现

在上一篇中,我们提到了,当我在我的电脑上试图复现Windows Defender带来的问题时,意外地发现了我的Dev-C++中文显示全部变成乱码。具体情况如下: https://gitee.com/michsong/blog-images/raw/master/20c9f02e36a9ba0f67be0613c2c006fe.jpg

解决方案

经过搜索后,找到如下解决方案: 控制面板-时钟和区域-区域-管理-更改系统和区域设置-取消勾选:Beta版:使用Unicode UTF-8提供全球语言支持

原理分析

前置知识

1. 字符编码
在计算机中,一切信息都是0和1。为了让计算机能够显示数字,人们定义了一套编码规则,即:变量存储的值是多少,根据规则就能对应到哪一个字符。
2. Code Page
在计算机发明的初期,由于只使用英文环境,故最早期的编码规则仅仅包含127个字符,即ASCII码。随着计算机在全球范围内的普及,我们需要不同的编码规则来存储不同国家的文字(在当时,不用同一套规则存储的原因我想是,这样每一个字符所需要的内存容量太大,早期的内存承受不起),于是,我们有了Code Page。Code Page即不同规则的集合,不同的Code Page定义了不同的语言中一个数据如何映射到一个字符。
3. Locale
这是Windows存储你的国家的方式。Locale 是一组定义用户语言、国家/地区及文化习俗(如日期格式、货币符号、排序规则)的参数集合,由 LCID (Locale ID) 标识。我们上文在控制面板中的区域部分,实际就是Locale。
4. ANSI
Windows中,ANSI即你当前的Locale所指向的代码页(即ANSI Code Page,ACP)。例如在中国,ANSI即为936(GBK)。
5. Unicode
Unicode,即万国码,是一套涵盖全世界几乎所有语言文字的编码标准。
6. UTF-8
UTF-8是一种Unicode的编码实现方式。与之对应的还有UTF-16,UTF-32等。他们的区别如下:

  1. UTF-32采用4字节存储,保证Unicode所有文字均可存储,但占用量较大。
  2. UTF-16采用2字节存储,可正确存储绝大部分常用语言的常用文字,但部分小众语言/生僻字/emoji表情需要两个2字节(代理对)来存储,处理起来较为麻烦,且英文等1字节即可存储的文字仍会产生空间浪费。
  3. UTF-8采用变长存储,实现了不同文字占用不同大小的内存,是目前最主流的解决方案。

7. Windows API
微软官方文档中指出,处理字符的 Windows API 函数通常有三种形态:

  • 通用版本:可根据编译宏自动切换。
  • ANSI 版本 (“A"后缀):例如 MessageBoxA。它是为了兼容老旧程序设计的,使用代码页规则。
  • Unicode 版本 (“W"后缀):例如 MessageBoxW。指示 “Wide”(宽字符),直接接收 UTF-16 编码,是内核的原生接口。

故障分析

有了前面相关概念的铺垫,分析故障原因便极其简单了。Dev-C++作为极其古早的IDE,采用的自然都是ANSI版本的API,也就是根据系统的ACP去决定字符的映射方式。彼时,Dev-C++对于简体中文,采用的仍然是GBK编码。但是,开启了Beta版:使用Unicode UTF-8提供全球语言支持,意味着我的Code Page被强制设定为65001(UTF-8),这与GBK的编码不同,当Dev-C++读取GBK编码的文字内容,并通过Windows API传递给系统时,出现了映射的错误,便产生了乱码。

最后

这期内容,是计算机基础知识的介绍,也是我一直一知半解的内容,趁着这个机会,也让自己弄清楚了这些概念之间到底有什么关系。
希望在AI日益进步的今天,我们都能够利用AI去学习这些知识,而不是把权利全权交给AI,让AI替自己完成全部的思考。