MultiByteToWideChar转换UTF-8中文为wchar_t显示异常问题
转换错误根本原因
- 核心诱因:传入
MultiByteToWideChar的待转换窄字符串并非合法UTF-8编码。绝大多数开发者直接在代码中写char* s = "中文";,MSVC编译器默认会将这类无修饰的窄字符串按照当前系统ANSI代码页(简体中文环境为CP936/GBK)编码存储,和UTF-8编码完全不兼容。此时强行指定CP_UTF8作为转换源代码页,本质是拿GBK字节流按UTF-8规则解析,必然输出乱码。 - 高频参数错误:
- 源代码页参数错传
CP_ACP而非CP_UTF8 - 转换标志位传值错误:UTF-8转宽字符时
dwFlags参数必须传0,传入MB_PRECOMPOSED等仅适用于ANSI代码页的标志会直接导致转换失败 - 长度参数传值错误:计算目标缓冲区长度时未正确处理字符串终止符,或传入的源串长度和实际字节数不匹配
- 源代码页参数错传
- 低概率兼容问题:Windows 2000及更早版本的Win32 API不支持
CP_UTF8参数,目前主流桌面系统已不存在该限制。
正确转码实现参考
// 保证窄字符串为UTF-8编码的两种通用方案 // 方案1:C++11及以上标准,用u8前缀强制字符串按UTF-8编码存储,不受编译器默认配置影响 const char* utf8_text = u8"测试中文内容"; // 方案2:MSVC编译器下加编译指令,全局指定窄字符串执行字符集为UTF-8 // #pragma execution_character_set("utf-8") // const char* utf8_text = "测试中文内容"; // 第一步:计算转换所需宽字符缓冲区长度 int wide_len = MultiByteToWideChar( CP_UTF8, // 源编码指定为UTF-8 0, // UTF-8转换必须传0标志 utf8_text, // 源UTF-8字符串 -1, // 自动识别\0结尾的源串长度 nullptr, // 空缓冲区先查长度 0 ); // 第二步:分配缓冲区执行转换 wchar_t* wide_text = new wchar_t[wide_len]; MultiByteToWideChar(CP_UTF8, 0, utf8_text, -1, wide_text, wide_len); // 第三步:调用MessageBoxW正常显示 MessageBoxW(nullptr, wide_text, L"弹窗标题", MB_OK); // 释放缓冲区 delete[] wide_text;
直接定义原生
wchar_t中文字符串可正常显示,是因为带L前缀的宽字符串会被编译器直接按Windows原生要求的UTF-16LE编码存储,不需要经过编码转换,自然不会出现乱码。
问题复现截图

内容的提问来源于stack exchange,提问作者Dmitry
相关产品推荐
相关产品推荐

