C++标准库不提供跨平台编码转换能力,std::string无编码语义,转换需依赖系统API或第三方库;Windows用MultiByteToWideChar/WideCharToMultiByte经UTF-16中转,Linux/macOS用iconv,跨平台推荐ICU或boost.locale。

直接说结论:C++标准库不提供跨平台的编码转换能力,std::string 本身不带编码语义,所谓“转成 UTF-8 / GBK / Shift-JIS 字节流”,本质是字符集间映射,必须依赖外部库或系统 API;硬用 std::wstring_convert(已弃用)或 std::codecvt(C++20 移除)会踩坑。
Windows 下用 MultiByteToWideChar + WideCharToMultiByte 转 GBK/UTF-8
这是最稳的路径——Windows API 原生支持多种 code page,且能精确控制错误处理。关键不是“怎么调”,而是“为什么必须分两步”:Windows 内部以 UTF-16(wchar_t)为中介,任何多字节编码(GBK、BIG5、Shift-JIS)和 UTF-8 都需经由宽字符中转。
-
CP_UTF8是常量 65001,CP_ACP表示当前系统 ANSI code page(中文 Windows 默认 GBK) - 目标缓冲区大小必须先调一次 API 获取长度(传
nullptr),再分配内存,否则易缓冲区溢出 - 若源字符串已是 UTF-8,想转 GBK:先用
CP_UTF8→wchar_t,再用CP_ACP→char;反向同理 - 错误处理建议设
WC_ERR_INVALID_CHARS和MB_ERR_INVALID_CHARS,避免静默替换为问号
Linux/macOS 下用 iconv 库做编码转换
iconv 是 POSIX 标准方案,但 C++ 里要手动管理句柄和内存。它不关心“字符串内容”,只认 char* + 长度 + 编码名(如 "UTF-8"、"GBK"、"ISO-8859-1"),所以输入必须是原始字节流,不能假设 std::string 是某种编码。
- 调用
iconv_open("GBK", "UTF-8")创建转换器,返回iconv_t句柄 -
iconv()的**inbuf和**outbuf是双重指针,会自动移动偏移,别传错地址 - 输出缓冲区必须预留足够空间(UTF-8 到 GBK 一般 1:1,但 GBK 到 UTF-8 可能 1:3,建议按输入长度 × 4 分配)
- 转换失败时
iconv()返回(size_t)-1,需检查errno:常见E2BIG(输出不够)、EILSEQ(非法序列)
跨平台项目推荐用 utf8cpp + icu 或 boost.locale
纯手工写平台分支太重,真要兼顾 Windows/Linux/macOS,icu 是事实标准(Chrome、Java 都用),但体积大;轻量级替代是 boost.locale(底层可选 icu 或系统 API),或者仅处理 UTF-8 ↔ UTF-16 用 utf8cpp(header-only,但不支持 GBK 等 legacy 编码)。
-
boost::locale::conv::between("你好", "UTF-8", "GBK")一行搞定,但需链接boost_locale库 - 若用
icu,核心是ucnv_fromUChars/ucnv_toUChars,所有编码名需用 ICU 格式("UTF8"、"GB18030",注意无短横) - 别依赖
std::codecvt_utf8:它只支持 UTF-8 ↔ UTF-16/32,且无法扩展到 GBK;C++20 已彻底删除该设施
最常被忽略的一点:编码转换前,必须确认源数据的真实编码。把 GBK 字节当 UTF-8 解码再转回 GBK,结果必然乱码——std::string 不是“字符串”,只是字节容器,它的 meaning 完全由你赋予。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











