编码不匹配
乱码的根本原因在于 编码不一致,计算机中的任何字符(包括英文字母和汉字)都需要用二进制数字来表示,这套规则就是“编码”。

(图片来源网络,侵删)
- 源代码文件编码:你写的
.c文件是用什么编码保存的? - 编译器默认编码:你的编译器(如 GCC, VS, Clang)在处理源文件时,默认使用什么编码?
- 终端/控制台编码:你用来运行和查看程序结果的终端(如 Windows 的 CMD、PowerShell,Linux/macOS 的 Terminal)是什么编码?
如果这三者不匹配,特别是汉字,就很容易显示为乱码。
解决方案
最可靠、最现代的解决方案是统一使用 UTF-8 编码,UTF-8 是一种全球通用的编码,可以表示世界上几乎所有的字符,并且是当前互联网和软件开发领域的事实标准。
统一使用 UTF-8 编码(推荐)
这是最推荐的方法,因为它一劳永逸,解决了跨平台和跨软件的兼容性问题。
步骤 1:确保你的源代码文件是 UTF-8 编码

(图片来源网络,侵删)
-
在 VS Code 中:
- 打开你的
.c文件。 - 看到右下角的状态栏,会显示当前文件的编码格式(很可能是
GBK)。 - 点击它,在弹出的菜单中选择 “通过编码保存...” (Save with Encoding)。
- 然后选择 UTF-8。
- 打开你的
-
在 Notepad++ 中:
- 打开你的
.c文件。 - 看到右下角的状态栏,会显示当前文件的编码格式。
- 点击它,选择 “转换为 UTF-8 编码” (Encode in UTF-8)。
- 打开你的
步骤 2:在代码中指定字符串的字面量编码
为了让编译器知道你的字符串 "你好,世界!" 是用 UTF-8 编写的,你需要在字符串前面加上 u8 前缀。

(图片来源网络,侵删)
#include <stdio.h>
int main() {
// u8 前缀告诉编译器,这个字符串是 UTF-8 编码的
const char* greeting = u8"你好,世界!";
printf("%s\n", greeting);
return 0;
}
步骤 3:确保终端使用 UTF-8 编码
-
在 Windows 上:
- 旧版 CMD:默认是 GBK,设置 UTF-8 比较麻烦,不推荐,建议使用 Windows Terminal。
- Windows Terminal (推荐):
- 打开 Windows Terminal。
- 点击下拉箭头,选择“设置” (Settings)。
- 选择你正在使用的 profile ("Command Prompt" 或 "PowerShell")。
- 在 "Advanced" 选项卡中,找到 "Text encoding"。
- 将其设置为 "UTF-8"。
- PowerShell (新版):在 Windows 11 和较新的 Windows 10 版本中,PowerShell 默认就是 UTF-8,通常无需设置。
-
在 Linux 和 macOS 上:
- 终端默认编码通常是 UTF-8,所以基本不需要任何设置,如果你的终端出现乱码,可以尝试执行
export LANG=en_US.UTF-8或export LC_ALL=en_US.UTF-8来临时设置。
- 终端默认编码通常是 UTF-8,所以基本不需要任何设置,如果你的终端出现乱码,可以尝试执行
只要你的 源文件、代码字符串 和 终端 三者都统一为 UTF-8,printf 就能正确输出中文,这是最稳定、最推荐的做法。
针对 Windows 平台的兼容方案(不推荐,仅作了解)
如果你的环境无法统一为 UTF-8(你被迫使用 GBK 编码的源文件和旧的 CMD 终端),你可以采取以下方法。
原理:告诉程序你的字符串是 GBK 编码的,然后让 CMD 终端用 GBK 编码去显示它。
方法 1:使用宽字符(wchar_t)和 wprintf
这种方法需要使用 Windows 特有的 API,代码会变得复杂且不跨平台。
#include <stdio.h>
#include <wchar.h> // 宽字符头文件
#include <locale.h> // 设置本地化信息的头文件
int main() {
// 设置控制台的区域设置为中文,这样 wprintf 才能正确输出
setlocale(LC_ALL, ".936"); // 936 是 GBK 的代码页
// 使用宽字符字符串 L""
wprintf(L"你好,世界!\n");
return 0;
}
- 注意:
setlocale(LC_ALL, ".936")是 Windows 特有的,在 Linux/macOS 上无效。wprintf和printf是不同的函数,格式化符号也略有不同(%hs用于窄字符,%ls用于宽字符)。- 这种方法破坏了代码的可移植性。
方法 2:直接使用 GBK 编码(不推荐)
如果你的源文件就是 GBK 编码保存的,并且终端也是 GBK,你可以直接写。
#include <stdio.h>
int main() {
// 这种方式依赖于源文件和终端都是GBK编码
printf("你好,世界!\n");
return 0;
}
- 缺点:
- 极其脆弱:换了台电脑、换个编辑器、换个终端,就一定会乱码。
- 不符合现代标准:GB2312/GBK 是中国旧的国标,现在已被 UTF-8 取代。
| 场景 | 推荐做法 | 优点 | 缺点 |
|---|---|---|---|
| 跨平台开发、新项目 | 统一使用 UTF-8 | 代码可移植性好,兼容性强,是未来的趋势 | 需要确保所有环境(IDE、终端)都支持 UTF-8 |
| 仅 Windows 环境,且无法更改设置 | 使用 wprintf 和 setlocale |
能在特定旧环境下工作 | 代码复杂,不跨平台,依赖 Windows API |
| 快速测试,不考虑移植性 | 直接使用 GBK 字符串 | 简单直接 | 极其脆弱,一换环境就出错,不推荐 |
对于任何新的 C 语言项目,请 坚定不移地选择方案一,将你的开发环境统一到 UTF-8 上,这会为你省去未来无数的麻烦。
一个完整的、可移植的 UTF-8 示例:
#include <stdio.h>
int main() {
// 1. 确保这个 .c 文件是 UTF-8 编码保存的。
// 2. 使用 u8 前缀明确字符串编码。
// 3. 确保你的终端是 UTF-8 编码。
const char* message = u8"你好,C语言!";
printf("Using UTF-8: %s\n", message);
return 0;
}
